贪婪和懒惰的正则表达式(理解题)

贪婪和懒惰的正则表达式(理解题)

我正在自学正则表达式,但我陷入了“贪婪”与“懒惰”的重复。

到目前为止我发现的是

  • “贪婪”意味着正则表达式寻找尽可能多的匹配项,其中
  • »lazy« 意味着正则表达式寻找尽可能少的匹配项

我发现的大多数文章都涉及a)在编程语言中使用它,而我却被困在grepegrep或b)使用grep -P激活Perl Mode;但由于我对 Perl 没有任何了解,所以这对我来说并不是很有帮助。

我的理解问题:我来到了这个大锤方法:

  • 惰性重复将寻找最短的可能匹配
  • 如果结果太长 → 调低中继器的音量?
  • 如果结果仍然太长→寻找另一个解决方案

这是我通过 HTML 代码的示例和实验得出的结论,我得到了一些但不是压倒性的结果。

如果有人能告诉我我的总结是否以及在哪里遗漏了一些重要观点,我将不胜感激。

答案1

这不是最短的比赛,只是一场短暂的比赛。贪婪模式尝试找到最后一个可能的匹配,惰性模式尝试找到第一个可能的匹配。但第一个可能的匹配不一定是最短的。

获取输入字符串foobarbaz和正则表达式o.*a(贪婪)或o.*?a(惰性)。

此输入字符串中可能的最短匹配项是oba

然而,正则表达式从左到右查找匹配项,因此会找到中的o第一个。如果模式的其余部分产生匹配,则它就保留在那里。ofoobarbaz

在第一个之后o.*(贪婪)吃掉obarbaz(整个字符串),然后回溯以匹配模式的其余部分(a)。因此它找到了最后一个 abaz并最终匹配oobarba

在第一个之后o.*?(惰性)不会吃掉整个字符串,而是查找模式其余部分的第一次出现。所以首先它看到第二个o不匹配的a,然后它看到b不匹配的a,然后它看到a匹配的a,因为它是懒惰的,所以它就停止了。 (结果是ooba,但不是oba

因此,虽然它不是最短的版本,但它比贪婪版本更短。

答案2

“Perl 模式”是指Perl 兼容正则表达式(PCRE)。 通俗地说,这是大多数现代语言本地使用的正则表达式样式,如果它们有内置的本机正则表达式 – Perl、Python、Ruby、PHP、JavaScript、Java – 尽管它们之间可能存在细微差别;从技术上讲,聚合酶链式反应源自但不完全相同的 perl 正则表达式引擎等,但如果您可以在其中一种语言中使用正则表达式,那么它们在其他语言中 99% 是相同的。它在它是一个选项的地方占主导地位,因为它是对现在被称为 POSIX regexps 的旧样式的改进,它是 grep 等老式工具的默认模式。

非贪婪,又名。懒惰的修饰符在使用 grep 匹配行的上下文中并不重要。这是因为不可能有完整的生产线匹配一个惰性表达式,而贪婪表达式则不会匹配,反之亦然。但是,如果使用开关,您可以看到差异,-o它显示匹配的段内容而不是整行(注意。这与实际显示的略有不同--color):

»echo "123 abc 456 def 789" > eg.txt
»grep -o -P "(\d+\s[A-Za-z]+\s)+" eg.txt
123 abc 456 def 
»grep -o -P "(\d+\s[A-Za-z]+\s)+?" eg.txt
123 abc 
456 def 
»grep -o -P "\d+\s[A-Za-z]+\s\d+" eg.txt
123 abc 456
»grep -o -P "\d+\s[A-Za-z]+\s\d+?" eg.txt
123 abc 4
56 def 7

如果您以这种方式使用 grep (使用-o),贪婪会产生影响。如果您使用 grep 来匹配包含模式的完整行,?那么无论哪种方式,非贪婪都无关紧要。

简而言之:贪婪匹配尽可能多匹配,非贪婪匹配尽可能少匹配。

相关内容