我正在自学正则表达式,但我陷入了“贪婪”与“懒惰”的重复。
到目前为止我发现的是
- “贪婪”意味着正则表达式寻找尽可能多的匹配项,其中
- »lazy« 意味着正则表达式寻找尽可能少的匹配项
我发现的大多数文章都涉及a)在编程语言中使用它,而我却被困在grep
和egrep
或b)使用grep -P
激活Perl Mode
;但由于我对 Perl 没有任何了解,所以这对我来说并不是很有帮助。
我的理解问题:我来到了这个大锤方法:
- 惰性重复将寻找最短的可能匹配
- 如果结果太长 → 调低中继器的音量
?
- 如果结果仍然太长→寻找另一个解决方案
这是我通过 HTML 代码的示例和实验得出的结论,我得到了一些但不是压倒性的结果。
如果有人能告诉我我的总结是否以及在哪里遗漏了一些重要观点,我将不胜感激。
答案1
这不是最短的比赛,只是一场短暂的比赛。贪婪模式尝试找到最后一个可能的匹配,惰性模式尝试找到第一个可能的匹配。但第一个可能的匹配不一定是最短的。
获取输入字符串foobarbaz
和正则表达式o.*a
(贪婪)或o.*?a
(惰性)。
此输入字符串中可能的最短匹配项是oba
。
然而,正则表达式从左到右查找匹配项,因此会找到中的o
第一个。如果模式的其余部分产生匹配,则它就保留在那里。o
foobarbaz
在第一个之后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 来匹配包含模式的完整行,?
那么无论哪种方式,非贪婪都无关紧要。
简而言之:贪婪匹配尽可能多匹配,非贪婪匹配尽可能少匹配。