非贪婪的正则表达式量词却得到了贪婪的结果。

6
我有一个使用 .net 正则表达式的测试,我正在使用 Windows Powershell 进行测试。输出结果如下:
> [System.Text.RegularExpressions.Regex]::Match("aaa aaa bbb", "aaa.*?bbb")


Groups   : {aaa aaa bbb}
Success  : True
Captures : {aaa aaa bbb}
Index    : 0
Length   : 11
Value    : aaa aaa bbb

我原本期望使用 ? 量词会导致匹配结果为 aaa bbb,因为第二组 a 已经足够满足表达式。我的非贪婪量词理解有误吗?还是我的测试方式不正确?
注意:这显然不是 正则表达式非贪婪变贪婪 问题。
4个回答

5

对字符串 aaa aaa bbb bbb 进行比较:

regex: aaa.*?bbb 
result: aaa aaa bbb

regex: aaa.*bbb
result: aaa aaa bbb bbb

正则表达式引擎会找到第一次出现的aaa,然后跳过所有字符(.*?)直到第一个bbb的出现,但对于贪婪操作符(.*)它会继续寻找更大的结果并因此匹配最后一个bbb的出现。


这是最清晰的解释,+1。 - duozmo

5
这是一个常见的误解。懒惰量词并不保证匹配最短的结果,它只能确保当前量词从当前位置开始时匹配的字符数不会超过整个匹配所需的字符数。
如果您真的希望确保最短的匹配结果,您需要明确地表达这一点。在这种情况下,这意味着您需要使用子正则表达式来匹配任何既不是aaa也不是bbb的内容。因此,得到的正则表达式将是:
aaa(?:(?!aaa|bbb).)*bbb

我只是做了我一开始应该做的事情,并查阅了Friedl的相关章节。那使我找到了aaa((?!aaa).)*bbb,这跟你说的差不多,只不过你的答案增加了让子表达式不捕获和在负向前瞻中测试bbb的细节。好答案。 - Dominic Cronin

1
这不是贪婪/懒惰的问题。问题在于你的字符串是从左到右分析的。当第一个aaa匹配时,正则表达式引擎逐个添加字符以获得完整的模式。
请注意,在贪婪行为下,在你的例子中,你会得到相同的结果:第一个aaa被匹配,正则表达式引擎获取所有最后的字符,并逐个回溯直到完成匹配。

0

这很简单,我们有以下字符串

aaa aaa bbb

让我们看看我们有这个正则表达式 aaa.*?bbb。 正则表达式引擎将从 aaa 开始

aaa aaa bbb

现在正则表达式引擎有了 .*?bbb。 它将继续进行 空格

aaa 空格 aaa bbb

但是我们仍然有一些字符直到 bbb? 因此,正则表达式引擎将继续匹配第二组 a

aaa aaa 空格 bbb

最后,正则表达式引擎将匹配 bbb

aaa aaa bbb


那么,如果我们只想匹配第二个aaa,我们可以使用以下正则表达式:

(?<!^)aaa.*?bbb,这意味着匹配不在句子开头的aaa

我们也可以使用aaa(?= bbb).*?bbb,这意味着匹配后面跟着空格 bbbaaa

看它工作的效果1 - 2

我突然想到,为什么不直接使用aaa bbb


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接