我正在阅读 PCRE 文档,我注意到所有格量词+
和一次性子模式(?>)
(也称为原子组)在概念上有些相似。有什么实质性的区别吗?
3 回答
(?>)
实际上是原子分组。
原子组是一个组,当正则表达式引擎从中退出时,会自动丢弃组内任何标记记住的所有回溯位置。原子团是非捕获的。语法是 (?>group)。
从regular-expressions.info上的所有量词:
占有量词是一种防止正则表达式引擎尝试所有排列的方法。这主要用于性能原因。您还可以使用所有格量词来消除某些匹配项。
从同一页面:
从技术上讲,所有格量词是一种将原子组放在单个量词周围的符号方便。所有支持所有格量词的正则表达式风格也支持原子分组。但并非所有支持原子分组的正则表达式风格都支持所有格量词。使用这些风味,您可以使用原子组获得完全相同的结果。
基本上,而不是
X*+
,写(?>X*)
。重要的是要注意量化标记 X 和量词都在原子组内。即使 X 是一个群,你仍然需要在它周围放置一个额外的原子群才能达到相同的效果。(?:a|b)*+
等于(?>(?:a|b)*)
但不等于(?>a|b)*
。后者是一个有效的正则表达式,但在用作更大的正则表达式的一部分时不会产生相同的效果。
如果您查看此页面的 regular-expressions.info,您会在表中注意到“x++
与(?>x+)
”相同。
唯一注意到的区别是:
占有量词是原子分组的有限但语法上更清晰的替代方案。
因此,它不像原子分组那样流行,但可以认为它更干净。
请注意,这与回溯的观点(?>X+)
并不完全相同。X++
因为在括号内,正则表达式引擎有回溯的可能性,因此正则表达式引擎总是记录原子组内的回溯位置(但一旦括号闭合就忘记它们),当然,它可以不是所有格量词的情况。例子:
考虑字符串aaaabbbb
(?>a+)ab
asa++ab
将失败,因为一旦原子组的括号关闭,正则表达式引擎就无法回溯。
但
(?>a+ab)
会成功,因为回溯位置总是记录在原子组内。
(?:a+|ab)+(?<!a)b
会成功,但(?>a+|ab)+(?<!a)b
会失败,因为括号在每次重复之间都是闭合的。
结论:(?>X+)
is not X++
but的确切同义词(?:X+){1}+