【问题标题】:Regex not as greedy as expected /^(\d+)[^_]/正则表达式不像预期的那么贪婪 /^(\d+)[^_]/
【发布时间】:2021-10-07 21:45:05
【问题描述】:

正则表达式/^(\d+)[^_]/gm
测试字符串12_34

我希望这个正则表达式不匹配测试字符串,因为 \d+贪婪 吃数字 12[^_]_ 上失败。

但它意外匹配仅与 Group1 中的 1。我哪里错了?

我试图找到一个与测试字符串“12”或“12xx”中的数字匹配但与“12_xx”不匹配的正则表达式

示例: https://regex101.com/r/0QRTjs/1/
方言:最后我会使用 Microsoft System.Text.RegularExpressions。

【问题讨论】:

  • 您应该阅读BacktrackingAtomic Groups。基本上,“贪婪”的意思是“尽可能允许回溯”。您期望的行为可以通过原子组实现。
  • 对于您的特定示例,您可以只使用否定的 Lookahead,因为您可能不需要在匹配中的数字后面包含字符:^(\d+)(?!\d|_)。见this demo
  • 好的,所以功能 Backtracking 导致我的“意外行为”,因为正则表达式比我想象的要多。我可以使用 Atomic Groups 来避免回溯。 ^((?>\d*))[^_] 似乎可以解决问题。谢谢艾哈迈德!
  • ^((?>\d*))([^_]|$) 正确匹配我的纯数字行。

标签: regex greedy


【解决方案1】:

\d+ 将匹配一个或多个数字。
由于您附加了[^_],因此它后面只能跟一个非_ 字符。
因此\d+ 无法匹配12,因为它后面跟着_
1 是第一个匹配组,因为它后面跟着2,而不是_

如果你只想匹配带有数字的行,有一个非常简单的表达式:

^(\d+)$

【讨论】:

    【解决方案2】:

    \d+ 有能力减少匹配的数量,如果这会导致整体匹配。通过回溯,2 满足[^_] 的匹配,1 被捕获。

    HERE

    您可以在比赛开始时使用负前瞻:

    /^(?!\d+_)(\d+)/
    

    HERE

    或者您可以使用不允许回溯的原子组:

    /^((?>\d+))(?:[^_]|$)/
    

    HERE

    或者使用所有格量词++,它不允许回溯:

    /^\d++([^_]|$)/
    

    HERE

    所有格量词可能是最快的......

    【讨论】:

    • (?!=_) 还不够,“12”仍会在“12_”中匹配。你需要(?![_\d])。另外,我猜= 是错字?
    • /^((?>\d+))[^_]/ 在仅数字行上出错。我在 cmets 中更正了我的答案。最好的似乎是@41686d6564 答案^(\d+)(?!\d|_)?
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2011-03-04
    • 1970-01-01
    • 2017-10-05
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多