正则表达式贪婪匹配不按预期工作

时间:2009-09-11 22:38:12

标签: regex regex-greedy

我有一个非常基本的正则表达式,我无法弄清楚为什么它不起作用所以问题是两部分。为什么我当前的版本不起作用,表达的正确性是什么。

规则非常简单:

  1. 必须至少有3个字符。
  2. 如果%字符是第一个字符,则必须至少包含4个字符。
  3. 因此,以下案例应该如下:

    • AB - 失败
    • ABC - 传递
    • ABCDEFG - 传递
    • % - 失败
    • %AB - 失败
    • %ABC - 传递
    • %ABCDEFG - 传递
    • %% AB - 传递

    我正在使用的表达式是:

    ^%?\S{3}
    

    对我来说意味着:

    • ^ - 字符串开头
    • %? - 贪心检查0或1%字符
    • \S{3} - 其他3个不是空格的字符

    问题是,%?由于某种原因没有进行贪婪的检查。如果它存在的话,它不会占用%字符,所以'%AB'的情况正在传递,我认为应该失败。为什么%?不吃%字符?

    有人请告诉我光明:)。

    修改:我使用的答案是下面的Dav:^(%\S{3}|[^%\s]\S{2}) 虽然这是一个2部分答案,艾伦真的让我理解为什么。我没有使用他的^(?>%?)\S{3}版本,因为它有效,但在javascript实现中却没有。这两个很好的答案和很多帮助。

4 个答案:

答案 0 :(得分:9)

正则表达式将始终尝试匹配整个模式 - 如果可以的话 - “贪婪”并不意味着“如果它存在则会永远抓住该角色”,而是意味着“如果它存在,将永远抓住该角色可以用它抓住“。

相反,你可能想要的是这样的东西:

^(%\S{3}|[^%\s]\S{2})

哪个匹配%后跟3个字符,或者非%,非空白后跟2个。

答案 1 :(得分:8)

您描述的行为不是贪婪,而是占有。正常的,贪婪的量词匹配尽可能多的匹配,但如果必要的话可以让整个正则表达式匹配(我喜欢将它们视为贪婪但容纳)。这就是你发生的事情:%?最初与领先的百分号匹配,但如果没有足够的字符用于整体匹配,它会放弃百分号并让\S{3}代替它。

一些正则表达式风格(包括Java和PHP)支持possessive quantifiers,它永远不会退缩,即使这会导致整体匹配失败。 .NET没有那些,但它有下一个最好的东西:atomic groups。无论你放在一个原子组中的什么行为就像一个单独的正则表达式 - 它要么在它应用的位置匹配,要么它不匹配,但它永远不会回来并尝试匹配比原来更多或更少的匹配因为其余的正则表达式失败(也就是说,正则表达式引擎永远不会将回溯到原子组)。以下是您如何使用它来解决问题:

^(?>%?)\S{3}

如果字符串以百分号开头,则(?>%?)与其匹配,如果没有足够的字符供\S{3}匹配,则正则表达式失败。

请注意,正如@Dav所示,原子组(或占有量词)不是解决这个问题的必要条件。但它们是非常强大的工具,可以很容易地区分不可能可能,或者太慢,光滑是

答案 2 :(得分:1)

我总是喜欢看RE问题,看看人们花了多少时间来“节省时间”

str.len() >= str[0]=='&' ? 4 : 3

虽然在现实生活中我会更明确,但我只是这样写,因为出于某种原因,有些人认为代码简洁是一种优势(我称之为反优势,但现在不是一个流行的观点)

答案 3 :(得分:0)

根据Dav的原始版本尝试修改一下正则表达式:

^(%\S{3,}|[^%\s]\S{2,})

使用正则表达式选项“^和$ line at line breaks”。