学习正则表达式 [已关闭]

Learning Regular Expressions [closed]

提问人: 提问时间:8/7/2008 最后编辑:5 revs, 4 users 67%Teifion 更新时间:11/11/2022 访问量:152616

问:

这个问题的答案是社区的努力。编辑现有答案以改进此帖子。它目前不接受新的答案或交互。

我真的不懂正则表达式。你能用一种通俗易懂的方式向我解释一下吗?如果有任何在线工具或书籍,您还能链接到它们吗?

正则表达式

评论


答:

856赞 19 revs, 18 users 52%Greg Bacon #1

最重要的部分是概念。一旦你了解了构建块的工作原理,语法上的差异就只不过是温和的方言而已。正则表达式引擎语法之上的一层是你正在使用的编程语言的语法。像 Perl 这样的语言消除了大部分的复杂性,但如果在 C 程序中使用正则表达式,则必须牢记其他注意事项。

如果您将正则表达式视为可以随意混合和匹配的构建块,那么它可以帮助您学习如何编写和调试自己的模式,以及如何理解其他人编写的模式。

从简单开始

从概念上讲,最简单的正则表达式是文字字符。该模式与字符“N”匹配。N

彼此相邻的正则表达式匹配序列。例如,该模式匹配序列“N”,后跟“i”,后跟“c”,后跟“k”。Nick

如果你曾经在 Unix 上使用过——即使只是为了搜索看起来很普通的字符串——你已经使用过正则表达式了!(in 是指正则表达式。grepregrep

从菜单中订购

只需增加一点复杂性,您就可以将“Nick”或“nick”与模式匹配。方括号中的部分是字符类,这意味着它正好匹配一个括起来的字符。您还可以在字符类中使用范围,以便匹配“a”或“b”或“c”。[Nn]ick[a-c]

该模式很特别:它不是只匹配文字点,而是匹配任何字符。这在概念上与真正的大字符类相同。.[-.?+%$A-Za-z0-9...]

将角色类视为菜单:只选择一个。

有用的快捷方式

使用可以为您节省大量键入时间,并且对于常见模式还有其他快捷方式。假设您要匹配一个数字:一种写法是 .数字是常见的匹配目标,因此您可以改用快捷方式。其他是(空格)和(单词字符:字母数字或下划线)。.[0-9]\d\s\w

例如,大写变体是它们的补码,因此可以匹配任何空格字符。\S

一次是不够的

从那里,您可以使用量词重复模式的某些部分。例如,模式匹配“abc”或“ac”,因为量词将其修改的子模式设置为可选。其他量词是ab?c?

  • *(零次或多次)
  • +(一次或多次)
  • {n}(正好n次)
  • {n,}(至少 n 次)
  • {n,m}(至少 n 次但不超过 m 次)

将其中一些块放在一起,该模式将所有[Nn]*ick

  • ick
  • 缺口
  • 缺口
  • 尼克
  • n尼克
  • 尼克
  • (依此类推)

第一场比赛展示了一个重要的教训:*总是成功的!任何模式都可以匹配零次。

其他一些有用的例子:

  • [0-9]+(及其等价物)匹配任何非负整数\d+
  • \d{4}-\d{2}-\d{2}匹配格式为 2019-01-01 的日期

分组

量词将模式修改到其紧靠的左侧。您可能希望匹配 '0abc0'、'0abcabc0' 等,但紧着加号量词左侧的模式是 。这意味着匹配 '0abc0'、'0abcc0'、'0abccc0' 等。0abc+0c0abc+0

要匹配一个或多个两端为零的“abc”序列,请使用 .括号表示可以量化为一个单元的子模式。正则表达式引擎保存或“捕获”与括号组匹配的输入文本部分也很常见。以这种方式提取位比计算索引和 更灵活,更不容易出错。0(abc)+0substr

交替

早些时候,我们看到了一种匹配“Nick”或“nick”的方法。另一个是交替,如 .请记住,交替包括左边的一切和右边的一切。使用分组括号来限制 的范围,例如 .Nick|nick|(Nick|nick)

再举一个例子,您可以等效地写成 ,但这可能是次优的,因为许多实现都假定备选项的长度大于 1。[a-c]a|b|c

逃避

虽然有些字符与自己匹配,但其他字符具有特殊含义。该模式与后跟小写字母 D 后跟加号的反斜杠不匹配:为此,我们将使用 .反斜杠会删除以下字符的特殊含义。\d+\\d\+

贪欲

正则表达式量词是贪婪的。这意味着它们可以匹配尽可能多的文本,同时允许整个模式成功匹配。

例如,假设输入是

“你好,”她说,“你好吗?

您可能希望只匹配“Hello”,然后当您看到它从“Hello”一直匹配到“you?”时,您会感到惊讶。".+"

要从贪婪切换到您可能认为的谨慎,请在量词中添加一个额外的内容。现在您了解了问题中的示例是如何工作的。它与文字左括号的顺序匹配,后跟一个或多个字符,并以右括号结束。?\((.+?)\)

如果您的输入是“(123) (456)”,则第一个捕获将是“123”。非贪婪量词希望允许模式的其余部分尽快开始匹配。

(至于你的困惑,我不知道任何正则表达式方言会做同样的事情。我怀疑在途中某处的传输中丢失了一些东西。((.+?))

使用特殊模式仅在输入的开头匹配,仅在输入的末尾匹配。用你的模式制作“书挡”,你说,“我知道前面和后面是什么,但给我中间的一切”是一种有用的技巧。^$

说您要匹配表单的注释

-- This is a comment --

你会写.^--\s+(.+)\s+--$

构建自己的

正则表达式是递归的,所以现在你已经了解了这些基本规则,你可以随心所欲地组合它们。

用于编写和调试正则表达式的工具:

免费资源

脚注

†:上面与任何字符匹配的陈述是出于教学目的的简化,并不完全正确。Dot 匹配除换行符以外的任何字符,但在实践中,您很少期望出现跨越换行符边界之类的模式。例如,Perl 正则表达式有一个 /s 开关和 Java Pattern.DOTALL,可以匹配任何字符。对于没有这种功能的语言,你可以使用类似的东西来匹配“任何空格或任何非空格”,换句话说,任何空格。."\n".+.[\s\S]

评论

17赞 Juraj.Lorinc 9/9/2015
您还可以使用试错法,而不是遵循在线正则表达式测试器和调试器可以提供巨大的帮助: regex101.com
3赞 3/31/2016
值得一提的是,尽管是类似的模式,但至少在 Javascript、Perl 和 Python 中不是这样。a{,m}
4赞 hek2mgl 11/15/2016
值得一提的是,有不同类型的正则表达式引擎,它们都有不同的功能集和语法规则。
1赞 Saurabh Hooda 8/16/2017
hackr.io/tutorials/learn-regular-expressions-regex 是查找最佳在线正则表达式教程的好地方。这里的所有教程都是由编程社区提交和推荐的(像 SO 一样被点赞)。
1赞 Lod 7/1/2019
这有助于快速参考:快速入门:正则表达式备忘单