【发布时间】:2010-09-05 12:09:21
【问题描述】:
我不太懂正则表达式。您能以易于理解的方式向我解释吗?如果有任何在线工具或书籍,您可以链接到它们吗?
【问题讨论】:
标签: regex
我不太懂正则表达式。您能以易于理解的方式向我解释吗?如果有任何在线工具或书籍,您可以链接到它们吗?
【问题讨论】:
标签: regex
最重要的部分是概念。一旦您了解了构建块的工作原理,语法上的差异只不过是温和的方言而已。正则表达式引擎语法之上的一层是您正在使用的编程语言的语法。 Perl 等语言消除了大部分复杂性,但如果您在 C 程序中使用正则表达式,则必须牢记其他注意事项。
如果您将正则表达式视为可以随意混合和匹配的构建块,它可以帮助您学习如何编写和调试自己的模式,以及如何理解其他人编写的模式。
从概念上讲,最简单的正则表达式是文字字符。模式N 匹配字符“N”。
彼此相邻的正则表达式匹配序列。例如,模式Nick 匹配序列“N”后跟“i”后跟“c”后跟“k”。
如果您曾经在 Unix 上使用过grep——即使只是为了搜索普通字符串——那么您已经在使用正则表达式了! (grep 中的re 指的是正则表达式。)
增加一点复杂性,您可以将 '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 中的交替。请记住,交替包括左侧的所有内容和右侧的所有内容。使用分组括号限制|的范围,例如,(Nick|nick)。
再举一个例子,您可以将[a-c] 等效地写为a|b|c,但这可能不是最理想的,因为许多实现都假设替代方案的长度大于1。
虽然有些字符匹配自己,但有些字符有特殊含义。模式 \d+ 不匹配反斜杠后跟小写 D 后跟加号:要得到它,我们将使用 \\d\+。反斜杠删除后面字符的特殊含义。
正则表达式量词是贪婪的。这意味着它们匹配尽可能多的文本,同时允许整个模式成功匹配。
例如说输入是
“你好,”她说,“你好吗?”
您可能认为".+" 只匹配“Hello”,然后当您看到它从“Hello”一直匹配到“you?”时会感到惊讶。
要从贪婪切换到您可能认为的谨慎,请在量词中添加一个额外的?。现在您了解了\((.+?)\),您问题中的示例是如何工作的。它匹配文字左括号的序列,后跟一个或多个字符,并以右括号结束。
如果您的输入是“(123) (456)”,那么第一次捕获将是“123”。非贪婪量词希望让模式的其余部分尽快开始匹配。
(至于您的困惑,我不知道任何正则表达式方言 ((.+?)) 会做同样的事情。我怀疑在传输过程中某处丢失了某些东西。)
使用特殊模式^ 仅匹配输入的开头,使用$ 仅匹配末尾。用你的模式制作“书挡”,你说“我知道前面和后面是什么,但把中间的一切都给我”是一种有用的技巧。
假设你要匹配表单的 cmets
-- This is a comment --
你会写^--\s+(.+)\s+--$。
正则表达式是递归的,所以现在您了解了这些基本规则,您可以随意组合它们。
†: 上面关于. 匹配任何字符的陈述是出于教学目的的简化,并非严格正确。点匹配除换行符"\n" 之外的任何字符,但实际上您很少期望.+ 之类的模式跨越换行符边界。 Perl 正则表达式有/s switch 和Java Pattern.DOTALL,例如,使. 匹配任何字符。对于没有此类功能的语言,您可以使用 [\s\S] 之类的内容来匹配“任何空格或任何非空格”,即任何内容。
【讨论】:
a{,m} 是一个类似的模式,但至少在 Javascript、Perl 和 Python 中不是一个东西。