非贪婪的正则表达式量词给出了贪心的结果

时间:2013-05-19 09:44:15

标签: .net regex non-greedy

我有一个.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足以满足表达式。我对非贪婪量词的理解是否有缺陷,或者我测试不正确?

注意:这与Regular Expression nongreedy is greedy

明显不同

4 个答案:

答案 0 :(得分:5)

比较字符串aaa aaa bbb bbb的结果:

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

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

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

答案 1 :(得分:5)

这是一种常见的误解。懒惰量词不保证尽可能短的匹配。它们只确保当前位置的当前量词与总体匹配所需的字符数不匹配。

如果您真的想确保尽可能短的匹配,则需要明确说明。在这种情况下,这意味着您需要一个与.*?aaa都不匹配的子规则,而不是bbb。因此产生的正则表达式将是

aaa(?:(?!aaa|bbb).)*bbb

答案 2 :(得分:1)

这不是一个贪婪/懒惰的问题。问题在于从左到右分析您的字符串。当第一个aaa匹配时,正则表达式引擎会逐个添加字符以获得完整的模式。

请注意,对于贪婪的行为,在您的示例中,您获得相同的结果:第一个aaa匹配,正则表达式引擎获取所有最后的字符并逐个字符地回溯,直到完全匹配。< / p>

答案 3 :(得分:0)

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

  

aaa aaa bbb

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

开头
  

aaa aaa bbb

正则表达式引擎现在.*?bbb。它将继续space

  

aaa 空间 aaa bbb

但我们在bbb之前仍有一些字符?所以正则表达式引擎将继续它的方式并匹配第二组

  

aaa aaa space bbb

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

  

aaa aaa bbb


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

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

我们也可以使用aaa(?= bbb).*?bbb,这意味着匹配aaa之后的space bbb

看到它正常工作 1 - 2

刚刚感觉到,但为什么不直接使用aaa bbb