最重要的部分是概念。一旦您理解了构建块的工作原理,语法上的差异就只不过是温和的方言而已。正则表达式引擎语法之上的一层是您所使用的编程语言的语法。Perl 等语言消除了大部分这种复杂性,但如果您在 C 程序中使用正则表达式,则必须牢记其他注意事项。
如果您将正则表达式视为可以随意混合搭配的构建块,它可以帮助您学习如何编写和调试自己的模式,以及如何理解他人编写的模式。
从简单开始
从概念上讲,最简单的正则表达式是文字字符。该模式 N
匹配字符“N”。
相邻的正则表达式匹配序列。例如,该模式 Nick
匹配序列“N”,后跟“i”,后跟“c”,后跟“k”。
如果您曾经 grep
在 Unix 上使用过——即使只是搜索普通的字符串——您就已经在使用正则表达式了!( re
in grep
指的是正则表达式。)
从菜单上点菜
稍微复杂一点,您可以使用模式匹配“Nick”或“nick” [Nn]ick
。方括号中的部分是 字符类 ,这意味着它与括号中的一个字符完全匹配。您还可以在字符类中使用范围,因此 [a-c]
匹配“a”或“b”或“c”。
该模式 .
很特殊:它不仅匹配文字点,还匹配 任何 字符†。从概念上讲,它与真正的大字符类相同 [-.?+%$A-Za-z0-9...]
.
将角色类别视为菜单:只选择一个。
实用快捷方式
使用 .
可以为您节省大量输入,并且还有其他常见模式的快捷方式。假设您想要匹配一个数字:一种写法是 [0-9]
。数字是常见的匹配目标,因此您可以使用快捷方式 \d
。其他是 \s
(空格)和 \w
(单词字符:字母数字或下划线)。
大写变体是它们的补充, \S
可以匹配任何 非 空白字符。
一次不够
用量词 重复模式的某些部分 。例如,模式 ab?c
匹配“abc”或“ac”,因为 ?
量词使它修改的子模式成为可选的。其他量词包括
-
*
(零次或多次)
-
+
(一次或多次)
-
{n}
(恰好 n 次)
-
{n,}
(至少 n 次)
-
{n,m}
(至少 n 次,但不超过 m 次)
把这些块放在一起,模式 [Nn]*ick
匹配所有的
第一次匹配说明了一个重要的教训: *
always succeeds! 任何模式都可以匹配零次。
其他一些有用的例子:
-
[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+--$
.
构建自己的
正则表达式是递归的,所以现在您了解了这些基本规则,您可以随意组合它们。
编写和调试正则表达式的工具:
图书
免费资源
-
RegexOne-通过简单、互动的练习进行学习。
-
正则表达式 - 您应该知道的一切 (PDF 系列)
-
正则表达式语法摘要
-
正则表达式的工作原理
-
JavaScript 正则表达式
脚注
†: 上述匹配任何字符的说法 .
是出于教学目的的简化,并非完全正确。点匹配除换行符之外的任何字符 "\n"
,但在实践中,您很少会想到这样的模式 .+
会跨越换行符边界。 /s
switch /s 开关 和 Java
Pattern.DOTALL .
匹配任何字符。对于没有此功能的语言,您可以使用类似 [\s\S]
匹配“任何空格或任何非空格”之类的东西,换句话说,匹配任何内容。