166

我真的不明白正则表达式。你能以易于理解的方式向我解释吗?如果有任何在线工具或书籍,您能否也链接到它们?

4

1 回答 1

824

最重要的部分是概念。一旦您了解了构建块的工作原理,语法上的差异只不过是温和的方言而已。正则表达式引擎语法之上的一层是您正在使用的编程语言的语法。诸如 Perl 之类的语言消除了大部分这种复杂性,但如果您在 C 程序中使用正则表达式,则必须牢记其他注意事项。

如果您将正则表达式视为可以随意混合和匹配的构建块,它可以帮助您学习如何编写和调试自己的模式,以及如何理解其他人编写的模式。

开始简单

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

彼此相邻的正则表达式匹配序列。例如,该模式Nick匹配序列“N”后跟“i”后跟“c”后跟“k”。

如果你曾经grep在 Unix 上使用过——即使只是为了搜索普通字符串——你已经在使用正则表达式了!(reingrep指的是正则表达式。)

从菜单中订购

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

该模式.很特殊:它不仅匹配文字点,还匹配任何字符†</sup>。它在概念上与真正的大字符类相同[-.?+%$A-Za-z0-9...]

将字符类视为菜单:只选择一个。

有用的快捷方式

使用.可以为您节省大量输入,并且还有其他常用模式的快捷方式。假设你想匹配一个数字:一种写法是[0-9]. 数字是一个常见的匹配目标,因此您可以改用快捷方式\d。其他是\s(空白)和\w(单词字符:字母数字或下划线)。

大写的变体是它们的补码,因此\S匹配任何空白字符,例如。

一次是不够的

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

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

将其中一些块放在一起,模式[Nn]*ick匹配所有

  • ick
  • 缺口
  • 缺口
  • 尼克
  • 尼克
  • 尼克
  • (等等)

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

其他一些有用的例子:

  • [0-9]+(及其等价物\d+)匹配任​​何非负整数
  • \d{4}-\d{2}-\d{2}匹配格式为 2019-01-01 的日期

分组

量词将模式修改到其紧邻的左侧。您可能希望0abc+0匹配 '0abc0'、'0abcabc0' 等,但紧靠加号量词左侧的模式是c. 这意味着0abc+0匹配“0abc0”、“0abcc0”、“0abccc0”等。

要匹配一个或多个末端为零的“abc”序列,请使用0(abc)+0. 括号表示可以量化为一个单元的子模式。正则表达式引擎保存或“捕获”与括号组匹配的输入文本部分也很常见。以这种方式提取位比计算索引和substr.

交替

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

再举一个例子,您可以等效地写[a-c]a|b|c,但这可能不是最理想的,因为许多实现都假设替代方案的长度大于 1。

逃跑

虽然有些字符匹配自己,但其他字符具有特殊含义。该模式\d+不匹配反斜杠后跟小写 D 后跟加号:要得到它,我们将使用\\d\+. 反斜杠从后面的字符中删除特殊含义。

贪婪

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

例如,假设输入是

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

您可能希望".+"只匹配“Hello”,然后当您看到它从“Hello”一直匹配到“you?”时会感到惊讶。

要从贪婪切换到您可能认为的谨慎,?请在量词中添加额外的内容。现在您了解了\((.+?)\)问题中的示例是如何工作的。它匹配文字左括号的序列,后跟一个或多个字符,并以右括号终止。

如果您的输入是“(123)(456)”,那么第一个捕获将是“123”。非贪婪量词希望让模式的其余部分尽快开始匹配。

(至于您的困惑,我不知道任何正则表达式方言((.+?))会在哪里做同样的事情。我怀疑在传输过程中某处丢失了某些东西。)

锚点

使用特殊模式^仅在输入的开头$匹配并仅在结尾匹配。用你的模式制作“书挡”,你说,“我知道前面和后面是什么,但把中间的一切都给我”是一种有用的技术。

假设您要匹配表单的注释

-- This is a comment --

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

建立你自己的

正则表达式是递归的,所以现在您了解了这些基本规则,您可以随意组合它们。

编写和调试正则表达式的工具:

图书

免费资源

脚注

†:以上匹配任何字符的陈述.是出于教学目的的简化,并非严格正确。点匹配除换行符之外的任何字符"\n",但实际上您很少期望诸如.+跨越换行符边界的模式。Perl 正则表达式有一个/sswitch和 Java Pattern.DOTALL,例如,可以.匹配任何字符。对于不具有此类功能的语言,您可以使用诸如[\s\S]匹配“任何空白或任何非空白”之类的东西,换句话说就是任何东西。

于 2010-05-03T16:09:21.150 回答