我不太懂正则表达式。你能用简单易懂的方式给我解释一下吗?如果有任何在线工具或书籍,你也可以链接到它们吗?
最重要的是概念。一旦你理解了构建块是如何工作的,语法上的差异就只不过是轻微的方言差异而已。正则表达式引擎语法之上的一层是您正在使用的编程语言的语法。像 Perl 这样的语言可以消除大部分这种复杂性,但是如果在 C 程序中使用正则表达式,则需要考虑其他因素。
如果您将正则表达式视为可以随意混合和匹配的构建块,那么它将帮助您学习如何编写和调试自己的模式,以及如何理解其他人编写的模式。
从概念上讲,最简单的正则表达式是文字字符。模式 N匹配字符“ N”。
N
相邻的正则表达式匹配序列。例如,模式 Nick匹配序列‘ N’后面跟着‘ i’后面跟着‘ c’后面跟着‘ k’。
Nick
如果您曾经在 Unix 上使用过 grepーー即使只是为了搜索普通的字符串ーー那么您已经使用了正则表达式!(grep中的 re指的是正则表达式。)
grep
re
只是增加了一点复杂性,您可以将“ Nick”或“ Nick”与模式 [Nn]ick进行匹配。方括号中的部分是 性格类,这意味着它正好匹配其中一个括起来的字符。您还可以在字符类中使用范围,因此 [a-c]匹配“ a”或“ b”或“ c”。
[Nn]ick
[a-c]
模式 .是特殊的: 它不仅仅匹配文字点,而且匹配 任何特征 。它在概念上与真正大的字符类 [-.?+%$A-Za-z0-9...]相同。
.
[-.?+%$A-Za-z0-9...]
把字符类想象成菜单: 只选择一个。
使用 .可以节省您大量的输入,并且对于常见模式还有其他快捷方式。假设您想匹配一个数字: 一种写入方法是 [0-9]。数字是一个频繁匹配的目标,所以您可以使用快捷方式 \d。其他的是 \s(空格)和 \w(单词字符: 字母数字或下划线)。
[0-9]
\d
\s
\w
大写变体是它们的补充,因此 \S匹配任何 不-空格字符,例如。
\S
从那里,你可以用 量词重复你的模式的一部分。例如,模式 ab?c匹配“ abc”或“ ac”,因为 ?量词使它修改的子模式成为可选的。其他量词包括
ab?c
?
*
+
{n}
{n,}
{n,m}
将其中的一些块放在一起,模式 [Nn]*ick匹配所有
[Nn]*ick
第一个匹配演示了一个重要的教训: *总是成功的!任何模式都可以匹配零次。
其他一些有用的例子:
[0-9]+
\d+
\d{4}-\d{2}-\d{2}
量词将模式修改为直接向左。您可能期望 0abc+0匹配“0abc0”、“0abcabc0”等等,但是加量词左边的模式 马上是 c。这意味着 0abc+0与“0abc0”、“0abcc0”、“0abccc0”等匹配。
0abc+0
c
若要将一个或多个“ abc”序列与末端的零进行匹配,请使用 0(abc)+0。括号表示可以量化为一个单位的子模式。正则表达式引擎保存或“捕获”输入文本中匹配括号组的部分也很常见。这种方法提取比特比计数索引和 substr更灵活,更不容易出错。
0(abc)+0
substr
早些时候,我们发现了一种匹配“ Nick”或“ Nick”的方法。另一种是 Nick|nick中的交替。记住交替包括左边的一切和右边的一切。使用分组括号来限制 |、 例如:。、 (Nick|nick)的范围。
Nick|nick
|
(Nick|nick)
另一个例子是,您可以等效地将 [a-c]编写为 a|b|c,但是这可能是次优的,因为许多实现假定替代方案的长度将大于1。
a|b|c
虽然有些字符与它们自己相匹配,但是有些字符有特殊的含义。模式 \d+不匹配反斜杠后跟小写 D 后跟加号: 为了得到这个结果,我们使用 \\d\+。反斜杠从下面的字符中移除特殊含义。
\\d\+
正则表达式量词是贪婪的。这意味着它们匹配尽可能多的文本,同时允许整个模式成功匹配。
例如,假设输入是
“你好,”她说,“你好吗?”
您可能期望 ".+"只匹配“ Hello”,然后当您看到它从“ Hello”一直匹配到“ You?'.
".+"
要从贪婪切换到你可能认为的谨慎,添加一个额外的 ?到量词。现在您了解了 \((.+?)\)是如何工作的,这个例子来自您的问题。它匹配文字左括号的序列,后跟一个或多个字符,并以右括号结束。
\((.+?)\)
如果您的输入是“(123)(456)”,那么第一个捕获将是“123”。非贪婪量化器希望允许模式的其余部分尽快开始匹配。
(至于你的困惑,我不知道任何正则表达式方言中 ((.+?))会做同样的事情。我怀疑有些东西在传输过程中丢失了。)
((.+?))
使用特殊模式 ^仅在输入的开头匹配,而 $仅在结尾匹配。用你的模式制作“书挡”,你说,“我知道前面和后面是什么,但给我之间的一切”是一个有用的技巧。
^
$
假设您想匹配表单的注释
-- This is a comment --
你会写 ^--\s+(.+)\s+--$。
^--\s+(.+)\s+--$
正则表达式是递归的,因此现在您已经理解了这些基本规则,可以按照自己的喜好组合它们。
上面关于 .匹配任何字符的说明是出于教学目的的简化,严格来说并不正确。点匹配除了换行 "\n"之外的任何字符,但是实际上你很少期望像 .+这样的模式跨越换行边界。例如,Perl 正则表达式有一个 /s开关和 JavaPattern.DOTALL,使 .完全匹配任何字符。对于没有这种特性的语言,您可以使用类似 [\s\S]的东西来匹配“任何空格或非空格”,换句话说,任何东西。
"\n"
.+
/s
Pattern.DOTALL
[\s\S]