原子组和非捕获组有什么区别?

10
  1. 什么是原子组((?>expr)),它有什么用处?在https://www.regular-expressions.info/atomic.html中,唯一的例子是当expr是交替表达式时,例如正则表达式a(?>bc|b)c匹配abcc但不匹配abc。是否有expr不是交替表达式的示例?
  2. 原子组和非捕获组((?:expr))是相同的吗?

1
请查看此帖子的修订历史,以查看海报包含的研究链接,在那里他们还要求举一个例子来更好地理解差异。第二个修订似乎使此答案失效。 - Scratte
是的,虽然我欣赏修改后的问题更加简洁明了,但它们在实质上改变了问题,并使我的答案失去了有效性,正如Scratte所指出的那样。 @double-beep,请重新考虑您的修改范围。 - Kal
不仅如此,编辑评论声称原子组是 PCRE 特有的显然是无意义的。例如,.NET 正则表达式支持原子组。 - Nick stands with Ukraine
3个回答

10
  1. 使用原子组时,如果给定的字符串未匹配完整个正则表达式,则正则引擎不会回溯查找更多排列。

    每当使用交替项时,如果成功匹配,则正则表达式将立即尝试匹配剩余的表达式,但它将跟踪其他交替可能出现的位置。如果没有匹配剩余的表达式,则正则表达式将返回先前记录的位置并尝试其他组合。如果使用了原子组,则正则表达式引擎将不会跟踪以前的位置,而只会放弃匹配。

    上述示例并没有解释使用原子组的目的,它仅演示了如何消除回溯。原子组将用于特定情况,在其中使用了贪婪量词,并且即使没有交替,仍可能存在进一步的组合。

  2. 原子组和非捕获组是不同的。非捕获组不保存匹配的值,而原子组在需要进一步组合时禁用回溯。

例如,正则表达式a(?:bc|b)c可以匹配abccabc(不捕获匹配),而a(?>bc|c)c只能匹配abcc。如果正则表达式是a(?>b|bc)c,它只会匹配abc,而a(?:b|bc)c仍然会匹配两者。


3
不要忘记,原子组也是非捕获的! - robinCTS

6

原子组(以及占有修饰符)可用于避免灾难性回溯-这可以被恶意用户利用,通过吞噬服务器的内存触发拒绝服务攻击。

非捕获组就是那样--非捕获。正则表达式引擎可以回溯到非捕获组;而不能回溯到原子组。


谢谢!原子组和占有修饰符之间有什么区别?它们是否用于相同的目的? - Tim
1
所有权修饰符只是原子的语法糖:(?:a|b)*+ 等同于 (?>(?:a|b)*) - Denis de Bernardy

0
有没有expr不是交替的例子?
考虑以下模式:
(abc)?a

这在abcabca中都能找到匹配。但是当可选部分变成原子时会发生什么?

(?>(abc)?)a

它不再在abc中找到匹配项。它永远不会放弃abc,所以最终的a失败了。

正如其他人所说,还有其他情况可能需要避免回溯,即使它对最终匹配没有影响,以优化您的正则表达式。


1
请注意,此帖子中的引用来自问题。请查看问题的第一个修订版本以了解这里发生了什么。 - Scratte

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接