【问题标题】:Non-greedy regex quantifier gives greedy result非贪心正则表达式量词给出贪心结果
【发布时间】:2013-05-19 09:44:15
【问题描述】:

我有一个 .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 不是同一个问题

【问题讨论】:

    标签: .net regex non-greedy


    【解决方案1】:

    这是一个常见的误解。惰性量词不能保证最短的匹配。他们只确保当前量词从当前位置开始匹配的字符不会超过整体匹配所需的字符数。

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

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

    【讨论】:

    • 我只是做了一开始就应该做的事,查阅了Friedl的相关章节。这使我找到了aaa((?!aaa).)*bbb,这或多或少是您所说的,只是您的答案添加了使子表达式不被捕获的附加细节,并且还在否定前瞻中测试了 bbb 。很好的答案。
    【解决方案2】:

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

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

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

    【讨论】:

    • 这是对正在发生的事情的最清晰的解释。 +1
    【解决方案3】:

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

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

    【讨论】:

      【解决方案4】:

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

      aaa aaa bbb

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

      开头

      aaa aaa bbb

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

      aaa 空格 aaa bbb

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

      aaa aaa 空间 bbb

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

      aaaaaa bbb


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

      (?<!^)aaa.*?bbb,表示匹配不在句首的aaa

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

      看看它是否工作1 - 2

      我才恍然大悟,你为什么不直接用aaa bbb呢?

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2016-02-29
        • 1970-01-01
        • 1970-01-01
        • 2013-06-16
        • 1970-01-01
        相关资源
        最近更新 更多