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

2024-05-13

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

规则非常简单:

  1. 必须至少包含 3 个字符。
  2. 如果 % 字符是第一个字符,则必须至少包含 4 个字符。

因此,以下情况应按如下方式处理:

  • AB——失败
  • ABC-通过
  • ABCDEFG-通过
  • % - fail
  • %AB - 失败
  • %ABC - 通过
  • %ABCDEFG - 通过
  • %%AB - 通过

我使用的表达是:

^%?\S{3}

这对我来说意味着:

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

问题是,%?由于某种原因没有进行贪心检查。它不会吃掉 % 字符(如果存在),因此“%AB”案例正在通过,我认为应该失败。为什么是%?不吃%字符?

请有人给我带来光明:)

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


您所描述的行为的词不是greedy, it's 所有格。正常的、贪婪的量词最初会尽可能多地匹配,但如果有必要的话会后退以允许整个正则表达式匹配(我喜欢将它们视为贪婪但包容)。这就是发生在你身上的事情:%?最初匹配前导百分号,但如果没有足够的字符来进行整体匹配,它会放弃百分号并让\S{3}而是匹配它。

一些正则表达式风格(包括 Java 和 PHP)支持所有格量词 http://www.regular-expressions.info/possessive.html,即使这会导致整个比赛失败,也永远不会后退。 .NET 没有这些,但它有其次的东西:原子团 http://www.regular-expressions.info/atomic.html。无论您在原子组中放入什么,都像一个单独的正则表达式一样 - 它要么在应用它的位置匹配,要么不匹配,但它永远不会返回并尝试比原来更多或更少匹配,只是因为其余的正则表达式失败(也就是说,正则表达式引擎永远不会回溯into原子团)。以下是您如何使用它来解决您的问题:

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

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

请注意,正如@Dav 所证明的那样,原子组(或所有格量词)并不是解决此问题所必需的。但它们是非常强大的工具,可以轻松区分不可能的 and possible, or 太慢了 and 尽可能光滑.

本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

正则表达式贪婪匹配未按预期工作 的相关文章

随机推荐