就目前而言,这个问题不适合我们的问答形式。我们希望答案得到事实、引用或专业知识的支持,但这个问题可能会引起辩论、争论、投票或扩展讨论。如果您觉得这个问题可以改进并可能重新打开,visit the help center为指导。
9年前关闭。
这个问题的答案是community effort .编辑现有答案以改进这篇文章。它目前不接受新的答案或互动。
我真的不明白正则表达式。你能用一种易于理解的方式向我解释它们吗?如果有任何在线工具或书籍,您是否也可以链接到它们?
最佳答案
最重要的部分是概念。一旦您了解了构建块的工作原理,语法上的差异就只不过是温和的方言而已。正则表达式引擎语法之上的一层是您正在使用的编程语言的语法。 Perl 等语言消除了大部分这种复杂性,但如果您在 C 程序中使用正则表达式,则必须牢记其他注意事项。
如果您将正则表达式视为可以随意混合和匹配的构建块,它可以帮助您学习如何编写和调试自己的模式,以及如何理解其他人编写的模式。
开始简单
从概念上讲,最简单的正则表达式是文字字符。模式 N
匹配字符“N”。
彼此相邻的正则表达式匹配序列。例如,模式 Nick
匹配序列 'N' 后跟 'i' 后跟 'c' 后跟 'k'。
如果你曾经在 Unix 上使用过 grep
——即使只是为了搜索普通的字符串——你已经在使用正则表达式了! (re
中的 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
匹配所有第一场比赛展示了一个重要的教训:
*
总是成功的!任何模式都可以匹配零次。其他一些有用的例子:
[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)
。再举一个例子,你可以等效地将
[a-c]
写成 a|b|c
,但这可能不是最理想的,因为许多实现假设替代品的长度大于 1。逃跑
虽然有些字符与自己匹配,但其他字符具有特殊含义。模式
\d+
不匹配反斜杠后跟小写 D 后跟加号:要得到它,我们将使用 \\d\+
。反斜杠删除以下字符的特殊含义。贪婪
正则表达式量词是贪婪的。这意味着它们匹配尽可能多的文本,同时允许整个模式成功匹配。
例如,假设输入是
"Hello," she said, "How are you?"
您可能期望
".+"
只匹配 'Hello',然后当您看到它从 'Hello' 一直匹配到 'you?' 时会感到惊讶。要从贪婪切换到您可能认为的谨慎,请向量词添加额外的
?
。现在您了解 \((.+?)\)
,您问题中的示例是如何工作的。它匹配文字左括号的序列,后跟一个或多个字符,并以右括号终止。如果您的输入是“(123) (456)”,则第一次捕获将是“123”。非贪婪量词希望允许模式的其余部分尽快开始匹配。
(至于你的困惑,我不知道
((.+?))
会做同样事情的任何正则表达式方言。我怀疑在传输过程中的某个地方丢失了一些东西。)anchor
使用特殊模式
^
仅在输入的开头匹配,使用 $
仅在结尾匹配。用你的图案制作“书挡”,你说“我知道正面和背面是什么,但给我之间的一切”是一种有用的技术。假设您要匹配表单的评论
-- This is a comment --
你会写
^--\s+(.+)\s+--$
。建立你自己的
正则表达式是递归的,所以现在您了解了这些基本规则,您可以随意组合它们。
用于编写和调试正则表达式的工具:
书籍
免费资源
脚注
†: 上面关于
.
匹配任何字符的陈述是出于教学目的的简化,并非严格正确。点匹配除换行符 "\n"
之外的任何字符,但在实践中,您很少期望像 .+
这样的模式跨越换行符边界。 Perl 正则表达式有一个 /s
switch 和 Java Pattern.DOTALL
,例如,使 .
匹配任何字符。对于没有这种特性的语言,你可以使用类似 [\s\S]
的东西来匹配“任何空白或任何非空白”,换句话说任何东西。
关于regex - 学习正则表达式,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/4736/