学习正则expression式

我不太了解正则expression式。 你能以简单易懂的方式向我解释吗? 如果有任何在线工具或书籍,您是否也可以链接到它们?

最重要的部分是概念。 一旦你理解了这些积木是如何工作的,语法上的差异只不过是轻度的方言而已。 正则expression式引擎语法之上的一个层是您正在使用的编程语言的语法。 像Perl这样的语言除去了大部分的复杂性,但是如果你在C程序中使用正则expression式的话,你必须记住其他的注意事项。

如果将正则expression式看作是可以随意混搭的构build块,则可以帮助您学习如何编写和debugging自己的模式,以及如何理解其他模式。

开始简单

从概念上讲,最简单的正则expression式是文字字符。 模式N匹配字符“N”。

彼此相邻的正则expression式匹配序列。 例如,模式Nick匹配序列“N”,接着是“i”,接着是“c”,接着是“k”。

如果你曾经在Unix上使用过grep ,即使只是寻找普通的string,你已经使用了正则expression式! ( grepre是指正则expression式。)

从菜单中订购

只增加一点复杂性,就可以将'Nick'或'nick'与模式[Nn]ick匹配。 方括号中的部分是一个字符类 ,这意味着它恰好匹配一个封闭的字符。 您还可以在字符类中使用范围,因此[ac]匹配“a”或“b”或“c”。

模式. 是特殊的:不是只匹配一个字面点,而是匹配任何字符 。 在概念上和真正的大字符类一样[-.?+%$A-Za-z0-9...]

把angular色类看作菜单:只选一个。

有用的捷径

使用. 可以为您节省大量的input,并且还有其他常见模式的快捷方式。 假设你想匹配非负整数:写一个方法是[0-9]+ 。 数字是一个频繁的匹配目标,所以你可以使用\d+匹配非负整数。 其他是(空格)和\w (单词字符:字母数字或下划线)。

大写的变体是它们的补充,所以\S匹配任何空白字符,例如。

一次是不够的

从那里,你可以用量词重复你的模式的一部分。 例如,abc模式匹配“abc”或“ac”,因为? 量词使得它修改的子模式是可选的。 其他量词是

  • * (零次或多次)
  • + (一次或多次)
  • {n} (正好n次)
  • {n,} (至lessn次)
  • {n,m} (至lessn次,但不多于m次)

把这些块放在一起,模式[Nn]*ick匹配全部

  • ICK
  • 缺口
  • 缺口
  • Nnick
  • nNick
  • nnick
  • (等等)

第一场比赛展示了一个重要的教训: *总是成功! 任何模式都可以匹配零次。

分组

量词将模式修改为其左侧。 您可能期望0abc+0匹配“0abc0”,“0abcabc0”等,但加号量词左侧的模式为c 。 这意味着0abc+0与“0abc0”,“0abcc0”,“0abccc0”匹配,依此类推。

要匹配一个或多个'abc'序列与末尾的零,请使用0(abc)+0 。 括号表示可以量化为一个单位的子模式。 正则expression式引擎保存或“捕获”与加括号的组相匹配的input文本部分也很常见。 以这种方式提取位比计数索引和substr更灵活,更不容易出错。

轮stream

早些时候,我们看到了一种匹配“尼克”或“尼克”的方法。 另一个是在Nick|nick交替。 请记住,交替包括左侧的一切,右侧的一切。 使用分组括号来限制|的范围 , 例如 (Nick|nick)

再举一个例子,你可以等价地把[ac]写成a|b|c ,但是这可能是次优的,因为许多实现假定备选将具有大于1的长度。

逃离

虽然有些人物相配,但其他人则有特殊的意义。 模式\d+不匹配反斜杠,接着是小写字母D,后跟一个加号:为了得到这个,我们使用\\d\+ 。 反斜杠从以下字符中删除特殊含义。

贪婪

正则expression式量词是贪婪的。 这意味着它们匹配尽可能多的文本,同时允许整个模式匹配成功。

例如,说input是

“你好,”她说,“你好吗?

你可能会希望".+"只匹配“你好”,当你看到从“你好”到“你”的匹配时,你会感到惊讶。

要从贪婪切换到您可能认为谨慎的地方,请添加额外的? 量词。 现在你明白\((.+?)\) ,你的问题的例子是如何工作的。 它匹配文字左括号的序列,后跟一个或多个字符,并以右括号结束。

如果你的input是'(123)(456)',那么第一个捕获将是'123'。 非贪婪量词希望允许模式的其余部分尽快开始匹配。

(至于你的困惑,我不知道任何正则expression方言((.+?))会做同样的事情,我怀疑在传播过程中有什么东西丢失了。

使用特殊模式^仅在input开始时匹配, $仅在最后匹配。 用你说的“你知道什么是在前面和后面,但是给我所有的东西”来形成“书挡”是一种有用的技巧。

假设你想匹配表单的评论

-- This is a comment --

你会写^--\s+(.+)\s+--$

build立你自己的

正则expression式是recursion的,所以现在你明白了这些基本规则,不pipe你喜欢什么,都可以把它们组合起来。

编写和debugging正则expression式的工具:

  • RegExr (用于JavaScript)
  • Perl: YAPE:正则expression式解释
  • 正规 教练 ( CL-PPCRE支持的引擎)
  • 正则expression式 (适用于JavaScript)
  • 正则expression式在线testing器
  • 正则expression式好友
  • 正则expression式101 (PCRE,JavaScript,Python,Golang)
  • 可视化RegExp
  • Expresso (用于.NET)
  • Rubular (ruby)
  • 正则expression式库 (用于常见场景的预定义正则expression式 )
  • Txt2RE
  • 正则expression式testing器 (适用于JavaScript)
  • 正则expression式风暴 (.NET)

图书

  • 掌握正则expression式 , 第二版和第三版 。
  • 正则expression式备忘录
  • 正则expression式食谱
  • 教你自己的正则expression式

免费资源

  • 正则expression式 – 你应该知道的一切 (PDF系列)
  • 正则expression式语法摘要
  • 正则expression式的工作原理

脚注

†:上面的陈述. 匹配任何字符是一个简化的教学目的,这是不严格的。 点匹配除换行符"\n"以外的任何字符,但在实践中,您很less会期望诸如.+类的模式跨过换行符边界。 例如Perl正则expression式有一个/s开关和Java Pattern.DOTALL . 匹配任何字符。 对于没有这种function的语言,可以使用类似[\s\S]来匹配“任何空格或任何非空格”,换句话说就是任何东西。