正则表达式不像预期的那么贪婪 /^(\d+)[^_]/

Posted

技术标签:

【中文标题】正则表达式不像预期的那么贪婪 /^(\\d+)[^_]/【英文标题】: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。

【问题讨论】:

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

以上是关于正则表达式不像预期的那么贪婪 /^(\d+)[^_]/的主要内容,如果未能解决你的问题,请参考以下文章

正则贪婪,非贪婪,分组,前瞻

python爬虫 正则表达式 re.finditer 元字符 贪婪匹配 惰性匹配

正则表达式之贪婪模式

负前瞻正则表达式贪婪(为啥.*?太贪婪)

Python 非贪婪正则表达式

正则表达式:贪婪与非贪婪