正则表达式不像预期的那么贪婪 /^(\d+)[^_]/
Posted
技术标签:
【中文标题】正则表达式不像预期的那么贪婪 /^(\\d+)[^_]/【英文标题】:Regex not as greedy as expected /^(\d+)[^_]/正则表达式不像预期的那么贪婪 /^(\d+)[^_]/ 【发布时间】:2021-10-07 21:45:05 【问题描述】:正则表达式:/^(\d+)[^_]/gm
测试字符串:12_34
我希望这个正则表达式不匹配测试字符串,因为 \d+
是 贪婪 吃数字 1
和 2
和 [^_]
在_
上失败。
但它意外匹配仅与 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+)[^_]/的主要内容,如果未能解决你的问题,请参考以下文章