代码之家  ›  专栏  ›  技术社区  ›  Kelsey

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

  •  4
  • Kelsey  · 技术社区  · 17 年前

    我有一个非常基本的正则表达式,我只是不明白为什么它不起作用,所以问题分为两部分。为什么我目前的版本不起作用,正确的表达是什么。

    1. 必须至少包含3个字符。

    因此,以下情况应按如下方式解决:

    • ABC通行证
    • ABCDEFG-通行证
    • %-失败
    • %AB-失败
    • %ABC通行证
    • %ABCDEFG-通行证

    我使用的表达式是:

    ^%?\S{3}
    

    • ^
    • %? -0或1%字符的贪婪检查
    • \S{3} -其他3个非空格字符

    出于某种原因,这不是贪婪的支票。如果存在,它不会吃掉%字符,所以“%AB”案例正在通过,我认为这应该是失败的。为什么 不吃%字符?

    有人请给我看看光:)

    编辑: ^(%\S{3}|[^%\s]\S{2}) 虽然这是一个由两部分组成的答案,艾伦的回答让我明白了原因。我没有用他的版本 ^(?>%?)\S{3} 因为它有效,但在javascript实现中无效。两个伟大的答案和很多帮助。

    4 回复  |  直到 14 年前
        1
  •  8
  •   Alan Moore Chris Ballance    17 年前

    你描述的行为不是 贪婪的 ,它是 占有欲强的 正常的、贪婪的量词尽可能多地匹配,但必要时会退缩,以允许整个正则表达式匹配(我喜欢把它们看作 贪婪但宽容 %? 最初匹配前导百分号,但如果没有足够的字符来进行整体匹配,它会放弃百分号,让 \S{3} 相反,匹配它。

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

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

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

    请注意,原子群(或所有格量词)不是解决这个问题所必需的,正如@Dav所证明的那样。但它们是非常强大的工具,可以很容易地区分 不可能 可能的 ,或 太慢了 尽可能地光滑 .

        2
  •  9
  •   Amber    17 年前

    如果可能的话,正则表达式将始终尝试匹配整个模式——“贪婪”并不意味着“如果存在,将始终抓取字符”,而是意味着“只要存在,将总是抓取字符” 抓住它就可以比赛了 ".

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

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

    它将匹配一个%后跟3个字符,或者一个非%、非空格后跟2个字符。

        3
  •  1
  •   Bill K    17 年前

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

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

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

        4
  •  0
  •   boxoft    17 年前

    尝试在Dav的原始正则表达式的基础上稍作修改的正则表达式:

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

    启用正则表达式选项“^和$换行符匹配”。