正则表达式神秘化:RegEx并不像看起来那么难

2020年12月30日10:53:35 发表评论 29 次浏览

通过Vijayabharathi Balasubramanian

你是那些因为它看起来像外语而远离正则表达式的人之一吗?我是一个。不再。

考虑一下你可以识别的所有声音, 交通标志和气味。正则表达式没有什么不同。就像分析字符串的手语一样。

今天, 我们将着眼于正则表达式。至少, 经常使用的表达式。

就像任何编程语言一样, 正则表达式本身就是一种简洁的语言。

在本文结尾处, 我们将知道如何充分利用正则表达式。我们将解决简单的问题并在此过程中学习负载。

你愿意投资30分钟并在RegEx启发下成长吗?然后安家。

为什么使用正则表达式?

我们每个人都有自己的"为什么", 不是吗?一种可能是测试字符串是否为有效的十六进制颜色代码。你可能正在编写一个处理器库, 例如萨斯利用RegEx。

我让宇宙抛弃为什么在你身上, 并帮助你覆盖怎么样.

0.准备好你的游乐场

参考文献

大多数情况下, 我发现此页面足以继续进行下去:来自MDN的正则表达式。实际上, 该页面就是你所需要的。你可以停止阅读这篇文章。马上。关闭此标签。 ?

还在我这儿?谢谢。你需要一个沙箱来玩耍。幸运的是, 你的浏览器上有一个沙箱。只需在浏览器控制台中使用DevTools。

熟悉语法

首先, 我们将使用/expression/.test('string')句法。

An表达是我们构建的任何正则表达式。一种String是被测试的字符串。的测试方法返回trueorfalse取决于比赛。

斜杠标记表达式的开始和结束。像对待双引号(")和单引号(')一样对待它们, 它们用于标记纯字符串的开头和结尾。

之间的表达/是文字。它们被视为文字字符。变量名称无法解析为其内容。

为了使其动态, 我们必须使用以下构造函数路线:新的RegEx(variable_name)句法。这将在职位后期挽救过来。

现在就做。只需在浏览器控制台中输入即可。

/a/.test("a"); //true
/a/.test("b"); //false

如果可行, 则准备就绪。不用担心它是什么。这就是我们将在以下几行中细分的内容。

让我们潜入……

1.从字母开始

让我们从小处开始。我们需要查找字符串是否具有特定字符。寻找角色一种在一个字符串中。

这是所有荣耀的表达:

/a/.test("abc"); //true 
/a/.test("bcd"); //false 
/a/.test("cba"); //true

该表达式可以满足我们的要求, "寻找一种在测试的字符串中"。就我们而言abc和bca确实有个性一种。但光盘没有它。

分解

现在, 这是很多斜杠和反斜杠。让我们分解一下。

我们已经看到了/表达/是我们构建正则表达式的方式。因此, 关于斜线在那里毫无疑问。实际上, 我们甚至可以将其分配给变量并使其看起来更好。

相同的代码:

let e=/a/; 
e.test("abc"); //true 
e.test("bcd"); //false 
e.test("cba"); //true

斜线之间的表达式只是一个字符一种就我们而言。我们只在寻找那个角色。

达到多字符

让我们扩展解决方案。

如果要查找多个字符怎么办?

按顺序放置它们。将它们视为子字符串。

这是一个例子:

/ab/.test("abacus"); //true 
/bac/.test("abacus"); //true  
/abc/.test("abacus"); //false 
/abas/.test("abacus"); //false

被测字符串应在斜杠中包含确切的表达式。如果满足该条件, 我们将获得一场比赛。

bac在算盘但阿巴斯不在算盘照原样。即使我们把那些字符弄乱了, 我们也没有完全匹配。

审查地面覆盖

符号/.../。斜杠(/)标记正则表达式的开始和结束。忽略点, 这就是我们放置图案的地方。的/一种/斜线之间的字符是在测试字符串上匹配的模式。的/ abc /在对被测字符串进行模式匹配测试期间, 将斜线之间的字符作为子字符串查找。

2.数字模式

让我们加一点香料。假设你要查找字符串中是否包含数字字符。

这里是:

let e=/0|1|2|3|4|5|6|7|8|9/;
e.test("42"); //true 
e.test("The answer is 42"); //true

首先, 该模式看起来很长。但是人物的长条纹一样可以用两个字符表示。我保留了本节末尾的内容, 以进行戏剧性的结尾。

第二种情况不应该是真的。我们待会儿再处理。

现在, 管道符号(|)的意思or。在正则表达式之外, 我们将其用作按位or和有条件的or双管(||)。是同一个人

我可以这么简单地称呼它为一天。但是你会尖叫得更好, 对吗?我们是开发商。我们一天中的大部分时间都在考虑更好的Bash和Git别名, 以节省几次击键。

我应该输入九个管道符号吗?没事

再来一次:

e=/[0123456789]/; 
e.test("42"); //true 
e.test("The answer is 42"); //still true

这个更好。将9个管道替换为2个方括号。保存了7个字符。击键次数减少了77.7%。

顺便说一句, 方括号内的任何内容都被视为要么这个or那。它是一个字符集。在我们的例子中, 字符串应包含0, 要么1, 要么2, 或者…与我一起负担, 我答应自己每天写1000个字, 或者3or4or5。好吧, 让我们停止。你懂了。

你在说什么?看起来还是很长吗?不满意?

好的, 我们再来一次:

e=/[0-9]/; 
e.test(42); //true 
e.test("42"); //true 
e.test("The answer is 42"); //true!

那个怎么样?看起来更干净, 不是吗?方括号内的任何内容[]手段or.0-9标记范围, 表示零到九。

因此, 测试在测试字符串中查找从零到九的字符。

如你所见, 测试也采用数字。

前缀和后缀模式

现在让我们解决第二种失败的情况。答案是42与我们的测试匹配, 因为我们的模式在某处寻找数字字符内字符串。没有开始到结束.

来吧^和$帮助我们。

  • ^意味着开始的字符串。他是双重代理人, 他将带我们离开。他的第二个头像仅在最后一节中显示。
  • $意味着结束的字符串。

让我们整理一下前缀模式:

/^a/.test("abc"); //true 
/^a/.test("bca"); //false 
/^http/.test("https://pineboat.in"); //true /^http/.test("ftp://pineboat.in"); //false

遵循的任何模式^应该在被测字符串的开头。

第二个字符串以b而我们的模式寻找一种。第四个寻找http而字符串以FTP。这就是他们失败的原因。

后缀图案

后缀模式如下。$模式的结尾指示测试寻找字符串的结尾。

/js$/.test("regex.js"); //true 
/js$/.test("regex.sj"); //false

听起来像是, "寻找js然后是字符串的结尾"。更好的是, "寻找结尾为js"。

模式匹配端到端

这就为模式匹配从头到尾铺平了道路, 你不妨称之为端到端。

let e=/^[0-9]$/ 
e.test("42"); //false - NO! 
e.test("The answer is 42"); //false 
e.test("7"); //true

令人惊讶的是, 当我们添加第一个失败时^和$.

/ ^ [0-9] $ /内容如下:"转到字符串的开头。寻找一个单数从字符集中。检查字符串是否就此结束。"这就是最后一个条目返回的原因true。它只是一个数字, 从头到尾。

那不是我们想要的。我们想测试字符串是否有一个或多个数字。

我们很亲。我们需要学习的最后一件事是如何指示模式在集合中查找多个字符。

三剑客的故事

问号(?), 一个好处 (+)和一个星号(*)在战场上相遇。每个人都有不同的眼光。

谦虚的问号(?)说:"我什么也看不到。"

加号(+)说:"我需要至少看到一个或多个。"

星号(*)说:"我俩都明白。我看不到一个或多个。"

其中之一巧妙地隐藏了他的能力。

问号首先登台:

/a?/.test(""); //true 
/a?/.test("a"); //true 
/a?/.test("b"); //true! 
/a?/.test("aa"); //true 
/^a?$/.test("aa"); //false
  • 匹配空字符串"
    as?代表0或1
  • 火柴一种
    一场比赛
  • 火柴b
    匹配0次出现
  • 火柴aa
    一场比赛, 第二场一种不是模式的一部分
  • / ^ a?$ /不匹配aa
    它寻找零或一一种, 开始到结束, 仅此而已, 仅此而已

加号(+)看着问号并说"我很感动, 但你的关注点是如此二元!"。并登台炫耀:

/a+/.test("a"); //true 
/a+/.test("aa"); //true 
/a+/.test("ba"); //true! 
/^a+$/.test("aa"); //true  
/a+/.test(""); //false 
/a+/.test("b"); //false 
/^a+$/.test("ab"); //false

记住加什么(+) 说过?它可以匹配一个或多个先前模式的出现。

所有回来的人true有一个或多个一种。我们甚至设法得到仅包含以下内容的整个字符串一种在最后一个返回true的/ ^ a + $ /.

false现在应该是有意义的, 但是最后一个单词返回false。/ ^ a + $ /寻找一种从头到尾, 不允许其他字符。这就是为什么ab测试失败。

最后, 加星号(*节目的)上台。他夸口说:"我可以单独对决, 也可以一次对决。"他说:"我可以匹配零个, 一个或多个"。

/a*/.test("a"); //true 
/a*/.test("aa"); //true 
/a*/.test("ba"); //true 
/a*/.test(""); //true 
/a*/.test("b"); //true 
/^a*$/.test("aa"); //true 
/^a*$/.test(""); //true  
/^a*$/.test("ab"); //false

除了最后一个, *能够处理所有其他内容。/ ^ a * $ /读为0或更多一种开始到结束。这就是为什么空字符串"通过测试并" ab"失败了

返回通用答案

还记得我们遇到三个火枪手之前在哪里吗?是的, "答案是42"。

现在, 如果我们只需要查找一个或多个数字, 请开始到结尾, 我们该怎么办?

//Let's throw in a plus 
let e=/^[0-9]+$/ 
e.test("4"); //true 
e.test("42"); //true 
e.test("The answer 42"); //false - Hurray

加号(+)在[0-9] +来救援。加号表示在其前面多次出现字符或图案。在我们的例子中, 有多个数字。

它也没有匹配我们最后一个案例答案是42因为在字符串的开头没有数字。

练习模式

  • 你可以尝试编写一个十六进制数字(由数字0–9和字母a-f组成, 并在前面带有可选的#)组成的模式吗?
  • 二进制数呢?你可以测试一个字符串是否仅包含0和1吗?

那戏剧性的结局

哦, 我差点忘了。[0-9]代表任何数字字符集, 也有简写形式\d.

let e=/^\d+$/; e.test("4"); //true e.test("42"); //true e.test("The answer 42"); //false - Hurray

只有两个字符表示数字。不, 没有比这更短的了。

有很多这样的特殊模式来指定簇, 例如数字(\d), 字母数字字符 (\w), 空格(\s)。

评论

  • [123]
    方括号中的表达式是一个字符集
    匹配的任何字符都将通过测试。只需一个字符。
  • [0-9]
    查找介于0到9之间的单个数字
  • [0-5]
    查找介于0到5之间的单个数字
  • [a-z]
    寻找a到z之间的单个字母
  • [A-F]
    寻找A到F之间的单个字母
  • [123] +
    加号(+)查找集合中的一个或多个字符。此匹配一个" 23132"子字符串, 该子字符串由较大的字符串" abc23132"中的1、2和3组成。
  • |
    管道符号代表or
  • \d
    数字的简写
    匹配一个数字。
  • \D
    非数字字符的简写
    除数字以外的任何其他内容\d

3.重复匹配以查找重复项

这是我要解决的实际问题。我深入研究了正则表达式, 最终导致了这篇文章。

系统已为你提供了一个字符串。找出日落之前是否注入了重复的字符。

以下是出现重复字符后立即出现的解决方案:

let e=/(\w)\1/; 
e.test("abc"); //false 
e.test("abb"); //true

表达式与字符串的任何部分都不匹配abc因为顺序中没有重复的字符。因此它返回false。

但它匹配bb字符串的一部分阿比并返回true。

继续, 在DevTool控制台上键入。看这个!

让我们将其分解为可以理解的部分。

反斜杠\释放

对于上一节中介绍的反斜线, 我一直保持沉默。对于那些到过那里和做到了, 这可能不足为奇。他们可能有逃脱了混乱。但是, 如果你不熟悉编程领域, 则需要了解有关反斜杠的更多信息。

在正则表达式语言中, 反斜杠是特殊的。反斜杠改变了其后的字符的含义。按门铃?

你叫什么\n当你遇到一个字符串?是的, 换行了。我们这里有类似的东西。

事实上, \n如果要查找新行, 则将其用作模式。那叫转义通常的含义ñ并给它一个全新的着装新队.

  • \d
    数字的简写
    匹配一个数字
  • \D
    非数字字符的简写
    除数字以外的任何其他内容\d
  • \s
    单个空格字符(例如空格, 换行或制表符)的简写。
  • \S的反义词\s
    除空白以外的任何东西
  • \w
    字母数字字符的简写
    匹配a-z, A-Z, 0-9和下划线_。
  • \W
    的反义词\w

可召回的比赛

我们从寻找重复字符的解决方案开始本节。/(\ w)\ 1 /匹配的" abb"。这表明正则表达式中内存的使用和调用。

考虑使用这种格式的方括号(表达)。记住与括号内的表达式匹配的结果字符串, 以备后用。

\1记住并使用括号内第一个表达式中的匹配项。同样\2从第二组括号中得出。等等。

让我们翻译一下我们的表情(\ w)\ 1简而言之:

匹配给定字符串上的任何字母数字字符。记住\1。检查该字符是否出现在第一个字符的旁边。

扩展1 —反向对

假设我们要查找两个字符, 它们以相反的顺序紧挨着出现。就像阿巴.ab反向为ba并彼此相邻。

这是表达式:

let e=/(\w)(\w)\2\1/; 
e.test("aabb"); //false 
e.test("abba"); //true 
e.test("abab"); //false

首先(\ w)火柴一种并记得\1。第二(\ w)火柴b并记得\2。然后表达式期望\2首先发生\1。因此, 阿巴是唯一与表达式匹配的字符串。

扩展2-无重复

这次, 我们将研究没有重复的字符序列。任何字符都不能跟在同一字符之后。干净利落。

在这里, 看看解决方案:

let e=/^(\w)(?!\1)$/; 
e.test("a"); //true 
e.test("ab"); //false 
e.test("aa"); //false

不是我们想要的, 而是接近的。中间不应该是假的。但是, 我们又添加了一些需要解释的符号。这意味着再次面对最强大的火枪手。

返回问号

记住我们先前遇到的三个火枪手。谦虚问号实际上是最强大的操纵器可以获取其他符号来进行竞标。也就是说, 如果你将反斜杠视为理所当然的话。

括号, 问号和感叹号的组合(?!), 称为展望。确切地说, 负面展望。a(?!b)火柴一种只有在不其次是b.

在JavaScript生态系统中, 感叹号表示不。但是它的表亲CSS掉头了, !重要意味着它实际上非常重要, 不应被覆盖。我差点滚过去陈的推文认为它不重要。我离题了。

另一方面, (?=)是积极的展望.a(?= b)火柴一种仅在其后b.

我们有一个解决方案。(\ w)(?!\ 1)寻找没有重复的字符。但仅适用于一个字符。我们需要将其分组, 并使用加号()查找1个或多个出现的字符+)。就这样。

let e=/^((\w)(?!\1))+$/; 
e.test("madam"); //false 
e.test("maam"); //false

但这似乎无效。如果我们将模式分组在方括号内, 例如((\ w)(?!\ 1)), \1不代表(\ w), 它代表对模式进行分组的高级括号对。所以失败了。

我们需要的是健忘分组选项。那就是问号, ?, 反击。它与冒号配对, (?:)并抹去括号可以带入的所有记忆功能。

最后一次:

let e=/^(?:(\w)(?!\1))+$/; 
e.test("madam"); //true 
e.test("maam"); //false

这次, 第一个级别的括号不记得了, 这要归功于?:, 因此, \1记得由传回的比赛\w.

它可以帮助我们使用加号+针对整体分组, 找到相似的字符对开始到结束, 这就像魔术。

用英语, "寻找字符。向前看以确保它后面没有相同的字符。从头到尾对所有角色执行此操作。"

评论

  • \w代表所有字母数字字符
    如果你将" w"大写并使用\ W', 这意味着所有字符以外字母数字
  • ()
    括号内的表达式会被记住以备后用
  • \1记住并使用括号内第一个表达式的匹配项
    \2从第二组括号中得出。等等。
  • a(?!b)
    括号, 问号和感叹号的组合(?!), 称为展望
    这个匹配一种只有在不其次是b
  • a(?= b)
    硬币的另一面
    比赛一种仅在其后b.(?:一种)
    健忘的分组
    寻找一种但不记得了
    你不能使用\1重用此匹配的模式

4.交替顺序

用例很简单。匹配仅使用两个字符的字符串。这两个字符应在字符串的整个长度上交替出现。将对" abab"和" xyxyx"进行两个样本测试。

这并不容易。我几次尝试都弄错了。这个回答指引我沿着正确的街道走。

解决方法如下:

let e=/^(\S)(?!\1)(\S)(\1\2)*$/; 
e.test("abab"); //true 
e.test("$#$#"); //true 
e.test("#$%"); //false 
e.test("$ $ "); //false 
e.test("xyxyx"); //false

你在这里说:"我受够了!"然后扔毛巾。

但是, 请等待Aha时刻!你距离金矿3英尺, 而不是停止挖掘的正确时间。

在得出"怎么样?’阿巴布火柴。$#$#匹配, 这与阿巴布.

#$%失败, 因为有第三个字符。$ $尽管它们是成对的, 但失败了, 因为我们的模式中排除了空格。

一切都很好, 除了y失败, 因为我们的模式不知道如何处理最后一个x。我们到达那里。

让我们来看看添加到皮带上的工具。它将很快变得有意义。

一次一件

你已经知道大部分内容。\S与...相反\s.\S寻找非空白字符。

现在是普通英语版本的/ ^(\ S)(?!\ 1)(\ S)(\ 1 \ 2)* $ /.

  • 从头开始/ ^
  • 寻找非空白字符(\ S)
  • 记住\1
  • 向前看, 看是否第一个字符后没有相同的字符(?!\ 1).
    记住这是一个负面展望.
  • 如果到目前为止我们还不错, 那就再找一个角色(\ S)
  • 记住\2
  • 然后寻找前两场比赛有0对或更多对 (\ 1 \ 2)*
  • 寻找这样的模式, 直到字符串结尾$ /

将其应用于我们的测试用例。"阿巴布"和" $#$#"比赛。

尾部

查看解决方案后, 你可能会认为这不需要单独的部分。但是它的简单是优雅的。让我们修复一个失败的案例y。如我们所见, 最后一个x是问题所在。我们有一个解决方案y。我们所需要的只是一个模式, 说"寻找可选的第一个字符"。

和往常一样, 让我们​​从解决方案开始。

let e=/^(\S)(?!\1)(\S)(\1\2)*\1?$/; e.test("xyxyx"); //true e.test("$#$#$"); //true

问号再次响起。没有逃脱他。我们最好让他成为我们的盟友, 而不是我们的敌人。问号?在一个字符或模式之后, 表示与前面的模式匹配为0或1。吞噬角色是不贪心的。

就我们而言\ 1?表示通过第一组括号记住的第一个字符的0或1个匹配项。

简单。放松。

评论

  • \S
    表示除空格以外的所有字符, 例如空格和换行符
    请注意, 它是大写S
  • a*
    星号或星号查找0个或多个出现的前一个字符。在这种情况下, 等于或大于0一种
    记住加号(+)寻找1个或更多?是的, 这些家伙是堂兄。
  • a(?!b)
    括号, 问号和感叹号的组合(?!)称为展望.
    这个匹配一种仅在其后没有b.
    例如, 它匹配一种inaa, ax, a$但不匹配ab
    尽管使用了方括号, 但它不记得后面的匹配字符一种.
  • \s
    小帽子s匹配单个空格字符, 例如空格或换行符。
  • a(?= b)
    这个匹配一种然后是b.
  • ^ ab * $
    你可能会认为这转化为0次或多次ab, 但符合一种其次是0或更多b
    例如:此匹配阿卜, 一种和ab, 但不匹配阿巴布
  • ^(ab)* $
    匹配0个或更多对ab
    这意味着它将匹配空字符串", ab和阿巴布, 但不是阿比
  • a?
    ?匹配0或1个出现的先前字符或模式
    \ 1?匹配第一次记忆的0或1次重​​复

5.匹配一个电子邮件地址

生产警告

仅正则表达式可能无法帮助验证电子邮件。甚至有人认为不应使用正则表达式, 因为它永远无法匹配100%的电子邮件。

考虑一下所有弹出的精美域名。还应考虑在电子邮件地址中包含符号, 例如点(。)和加号(+)。

你需要两次验证电子邮件。一旦在客户端, 可以帮助用户避免拼写错误的地址。从语义输入标签类型开始<input type ='email'>。一些浏览器会自动验证它, 而无需在前端添加任何脚本。

通过实际发送确认电子邮件, 再次在服务器上对其进行验证。

你最近没见过这样的人吗?只是尝试订阅这个松船。你会收到一封实际的电子邮件, 要求你确认是否属于你。该确认充分证明你的电子邮件有效。

那是一帆风顺的, 不是吗?

电子邮件正则表达式

现在我们添加了免责声明, 你实际上是想看到一种模式吗?否, 搜索电子邮件地址的正则表达式。一个这样的结果来自perl模块超过一页。

因此, 我什至不会尝试。如此长的正则表达式由计算机通过模式生成器生成。不是像我们这样的凡人。

6.匹配强密码

如果你是个咖啡人, 那么这是获得健康的最佳时机。因为我们在这篇文章的最后一节, 但到目前为止是最长的一节。

它引入了很少的新运算符和模式。但是它重用了许多模式。与往常一样, 我们保留最短的最优化的最后一个。

ASCII范围是本文的最佳部分。因为, 我在研究这篇文章的同时学习了它。

现在, 问题了。还记得注册表格在满足你的强密码要求之前进行了几次尝试吗?弱, 好, 强和非常强?是的, 我们将建立该验证。

密码应为:

  • 至少4个字符
  • 包含小写
  • 包含大写
  • 包含一个数字
  • 包含符号

这是一个棘手的问题。开始使用信件后, 你将无法再检查它们是否满足其他条件。 我们的线索就在这里。我们不能回头, 但我们可以向前看!

字符串长度

我们首先测试一下字符串密码是否为4个字符长。很简单采用。长度在密码字符串上。完成了吧?不, 谁需要一个简单的解决方案?让我们加香料吧。

//expression with just lookahead
//wouldn't consume any character
e1=/^(?=.{4, })$/; 
e1.test("abc") //false
e1.test("abcd") //false  

//after lookahead, //pattern to consume character is needed.
e2=/^(?=.{4, }).*$/; 
e2.test("abc") //false 
e2.test("abcd") //true
  • 你可能还记得(?=)从我们以前的工作"没有重复"这是一种前瞻性使用
    它不消耗任何字符
  • 点(.)是一个有趣的角色
    它的意思是, 任何字符.
  • {4, }
    代表至少4个前面的字符, 没有最大限制
  • \ d {4}
    会寻找正好4个数字
  • \ w {4, 20}
    将寻找4到20个字母数字字符

让我们翻译/^(?=.{4, })$/。 "从字符串的开头开始。至少要看4个字符。不记得比赛了。回到开头, 检查字符串是否在此处结束。"

听起来不对。可以?至少是最后一点。

这就是为什么我们引入变化/^(?=.{4, }).*$/。一个额外的点和一个星星。内容如下:"从头开始。期待4个字符。不记得比赛了。回到开始。使用以下所有字符。*看看是否到达字符串的末尾。"

现在这很有意义。是不是

这就是为什么abc失败并且A B C D通过模式。

至少一个号码

这将很容易。

e=/^(?=.*\d+).*$/ 
e.test(""); //false 
e.test("a"); //false 
e.test("8"); //true 
e.test("a8b"); //true 
e.test("ab890"); //true

从字符串的开头/ ^。提前寻找0个或更多字符?=。*。检查后面是否有1个或多个数字\ d +。匹配之后, 请重新开始(因为我们处于前进状态)。消耗字符串中的所有字符, 直到字符串末尾。* $ /.

至少一个小写字母

这个遵循与上面相同的模式。

e=/^(?=.*[a-z]+).*$/; 
e.test(""); //false 
e.test("A"); //false 
e.test("a"); //true

翻译?当然。 "从……开始吧。"代替\ d +, 我们有[a-z] +这是来自的字母字符集一种tož.

至少有一个大写字母

我们不要过分杀伤力。[A-Z]代替[a-z]从上一节开始。

至少一个符号

这将是具有挑战性的。匹配符号的一种方法是将符号列表放置在字符集中。/^(?=.*[-+=_)(\*&\^%\$#@!~"':;|\}]{[/?.>, <]+).*$/。测试(" $")就是字符集中的所有符号。必要时适当逃脱。我用普通的英语写它可能要花几个月的时间。

因此, 为了使我们所有人摆脱永恒的痛苦, 这里有一个简单的例子:

//considers space as symbol 
let e1; 
e1=/^(?=.*[^a-zA-Z0-9])[ -~]+$/ 
e1.test("_"); //true 
e1.test(" "); //true  

//does not take space 
let e2; 
e2=/^(?=.*[^a-zA-Z0-9])[!-~]+$/ 
e2.test(" "); //false 
e2.test("_"); //true  

//the underscore exception 
let e3; 
e3=/^(?=.*[\W])[!-~]+$/ 
e3.test("_"); //false

等等那是什么^从中间再来没有地方?如果你已经走到了这一步, 那么你就会在这里意识到朴素无辜^标记字符串开头的是双重代理。这意味着结束并不算太远。他被暴露了。

在一个字符集中, ^否定字符集。那是, [^ a-z]意思是除一种tož.

[^ a-zA-Z0-9]然后代表小写字母, 大写字母和数字以外的任何字符。

我们本来可以使用\W而不是长字符集。但\W代表所有字母数字字符包括下划线_。如你在上面的第三组示例中看到的那样, 它将不会接受下划线作为有效符号。

字符集范围

奇怪的情况[!-〜]。它们在键盘中彼此相邻, 但是其ASCII值对角相反。

还记得a-z吗? A-Z? 0-9?这些不是常数。它们实际上是基于其值的ASCII范围。

的ASCII表有125个字符。零(0)到31与我们无关。空格从32开始一直到126(即tilda(〜))。感叹号是33。

So[!-〜]涵盖了我们需要的所有符号, 字母和数字。这个想法的种子来自另一个解决方案符号问题。

组装部队

综上所述, 我们得到了一个看起来不错的正则表达式/^(?=.{5, })(?=.*[az]+)(?=.*\d+)(?=.*[AZ]+)(?=.*[^\w]) [-〜] + $ /.

那开始困扰着我们。尽管我们一直在单独研究它们。

这是用于动态构建表达式对象的语法派上用场的地方。我们将分别制造每个零件, 然后再组装它们。

//start with prefix 
let p = "^"; 

//look ahead  
// min 4 chars 
p += "(?=.{4, })"; 
// lower case 
p += "(?=.*[a-z]+)"; 
// upper case 
p += "(?=.*[A-Z]+)"; 
// numbers 
p += "(?=.*\\d+)"; 
// symbols 
p += "(?=.*[^ a-zA-Z0-9]+)"; 
//end of lookaheads  

//final consumption 
p += "[ -~]+";  
//suffix 
p += "$"; 

//Construct RegEx 
let e = new RegEx(p); 
// tests 
e.test("aB0#"); //true  
e.test(""); //false 
e.test("aB0"); //false 
e.test("ab0#"); //false 
e.test("AB0#"); //false 
e.test("aB00"); //false 
e.test("aB!!"); //false  

// space is in our control 
e.test("aB 0"); //false 
e.test("aB 0!"); //true

如果你还不疲倦, 那么你会发现上面的代码中有两种奇怪的语法。

  • 一, 我们没有使用/ ^, 相反, 我们只使用了^。我们没有使用$ /要么结束表达式, 要么只是$.
    原因是正则表达式构造函数会自动为我们添加开始和结尾斜杠。
  • 二, 匹配我们使用的数字\\ d而不是通常的\d。这是因为变量p只是双引号内的普通字符串。要插入反斜杠, 你需要对反斜杠本身进行转义。
    \\ d决心\d在正则表达式建设者

显然, 服务器端也应该对密码进行验证。如果你的框架或语言尚无法解决SQL注入漏洞, 请考虑一下。

7.结论

这把我们带到了故事的结尾。但这是旅程的开始。

我们只是将RegEx的模式匹配部分与测试方法。执行方法基于此基础, 以基于模式返回匹配的子字符串。

字符串对象具有如下方法比赛, 搜索, 更换和分裂广泛使用正则表达式。

希望这使你能够对RegEx的组成模式有扎实的了解, 从而进一步探索这些功能。

8.号召性用语

不, 在我们克服了所有困难之后, 我不再要求你订阅。

只是制作好的软件。

如果此处提供的任何代码块均不起作用, 请对此发表评论github问题我是专门为此帖子创建的。

希望它有用!如果其他人将从中受益, 请分享。

你真棒。感谢你的时间。根据最新的标准, 此内容已久。谢谢阅读。

最初发表于www.pineboat.in.

一盏木

发表评论

:?: :razz: :sad: :evil: :!: :smile: :oops: :grin: :eek: :shock: :???: :cool: :lol: :mad: :twisted: :roll: :wink: :idea: :arrow: :neutral: :cry: :mrgreen: