就目前而言,此问题不适合我们的问答形式。我们希望答案能得到事实、参考资料或专业知识的支持,但此问题可能会引发辩论、争论、投票或更长时间的讨论。如果您认为此问题可以改进并可能重新讨论,请visit the help center寻求指导。
10年前关闭。此问题的答案为community effort。编辑现有答案以改进此帖子。当前不接受新答案或互动。
“我不太懂正则表达式,你能不能给我简单易懂的解释一下?如果有什么在线工具或者书籍,你能不能也链接一下?”
就目前而言,此问题不适合我们的问答形式。我们希望答案能得到事实、参考资料或专业知识的支持,但此问题可能会引发辩论、争论、投票或更长时间的讨论。如果您认为此问题可以改进并可能重新讨论,请visit the help center寻求指导。
10年前关闭。此问题的答案为community effort。编辑现有答案以改进此帖子。当前不接受新答案或互动。
“我不太懂正则表达式,你能不能给我简单易懂的解释一下?如果有什么在线工具或者书籍,你能不能也链接一下?”
1条答案
按热度按时间iezvtpos1#
最重要的部分是概念。一旦你理解了构建块是如何工作的,语法上的差异就只不过是轻微的方言。在你的正则表达式引擎语法之上的一层是你正在使用的编程语言的语法。像Perl这样的语言消除了这种复杂性的大部分,但是如果你在C程序中使用正则表达式,你必须记住其他的注意事项。
如果您将正则表达式视为可以随意混合和匹配的构建块,它将帮助您学习如何编写和调试自己的模式,以及如何理解其他人编写的模式。
简单开始
从概念上讲,最简单的正则表达式是文字字符。模式
N
匹配字符“N”。彼此相邻的正则表达式匹配序列。例如,模式
Nick
匹配序列“N”后跟“i”后跟“c”后跟“k”。如果您曾经在Unix上使用过
grep
--即使只是搜索看起来很普通的字符串--那么您已经在使用正则表达式了!(grep
中的re
指的是正则表达式。)菜单中的订单
增加一点复杂性,你可以用模式
[Nn]ick
匹配'Nick'或'nick'。方括号中的部分是一个 * 字符类 *,这意味着它只匹配一个括起来的字符。你也可以在字符类中使用范围,所以[a-c]
匹配'a'或'b'或'c'。模式
.
比较特殊:它不是只匹配一个字符点,而是匹配 any character†。它在概念上与真正的大字符类[-.?+%$A-Za-z0-9...]
相同。将角色类视为菜单:只选一个。
有用的快捷方式
使用
.
可以保存大量的输入工作,而且还有其他一些常见模式的快捷方式。一种写法是[0-9]
。数字是一个频繁的匹配目标,因此您可以使用快捷键\d
。其他写法是\s
(空格)和\w
(单词字符:字母数字或下划线)。大写的变体是它们的补码,因此
\S
匹配任何 * 非 * 空格字符。一次是不够的
从这里,你可以用 * 量词 * 重复模式的一部分。例如,模式
ab?c
匹配'abc'或'ac',因为?
量词使它修改的子模式成为可选的。其他量词是*
(零次或多次)+
(一次或多次){n}
(正好 n 次){n,}
(至少 n 次){n,m}
(至少 n 次,但不超过 m 次)将这些块中的一些放在一起,模式
[Nn]*ick
匹配所有第一场比赛证明了一个重要的教训:*
*
总是成功!* 任何模式都可以匹配零次。其他一些有用的示例:
[0-9]+
(及其对等的\d+
)符合任何非负整数\d{4}-\d{2}-\d{2}
匹配格式类似2019-01-01的日期分组
数量词会修改紧靠其左边的模式。您可能会预期
0abc+0
会符合'0abc 0'、'0abcabc 0'等等,但是加号数量词左边的模式 * 立即 * 是c
。这表示0abc+0
会符合'0abc 0'、'0abcc 0'、'0abccc 0'等等。要匹配一个或多个结尾为零的“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'。非贪婪量词希望允许模式的其余部分尽快开始匹配。
(As让您感到困惑的是,我不知道有什么正则表达式方言可以让
((.+?))
做同样的事情。锚钉
使用特殊的模式
^
只匹配输入的开头,使用$
只匹配输入的结尾。用你的模式做“书挡”,你可以说,“我知道前面和后面是什么,但是给予我中间的所有东西”是一个有用的技巧。假设您要匹配表单的注解
x1米45英寸
您应该写为
^--\s+(.+)\s+--$
。建立您自己的
正则表达式是递归的,因此现在您已经了解了这些基本规则,可以按照自己的喜好合并它们。
编写和调试正则表达式的工具:
本书
释放资源
注脚
**†:**上面的声明
.
匹配任何字符是为了教学目的的简化,严格来说并不正确。点匹配除换行符"\n"
之外的任何字符,但在实践中,你很少会想到像.+
这样的模式会跨越换行符边界。例如,Perl正则表达式有一个/s
开关和JavaPattern.DOTALL
,可以使.
匹配任何字符。对于没有这样一个特性的语言,你可以使用像[\s\S]
这样的模式来匹配“任何空格或任何非空格”,换句话说,任何东西。