占有量词和一次性子模式的区别

6

我正在阅读PCRE文档,发现占有量词+和一次性子模式(?>),也称为原子组,在概念上有些相似。它们之间是否有实质性的区别呢?


这是一个非常好的问题,我在寻找答案的过程中学到了新的东西。 - anubhava
请参阅《精通正则表达式》中相关的引用。 - ridgerunner
3个回答

8
(?>)实际上是原子组。根据regular-expressions.info的描述,当正则表达式引擎退出原子组时,自动丢弃组内任何标记记住的所有回溯位置。原子组不捕获匹配项。语法为(?>group)。
regular-expressions.info了解到,占有量词是一种防止正则表达式引擎尝试所有排列组合的方法。这主要用于性能优化。您还可以使用占有量词来消除某些匹配项。
从同一页面了解到:技术上讲,占有量词是一个方便的符号,将原子组放在单个量词周围。支持占有量词的所有正则表达式都支持原子组。但是,并非所有支持原子组的正则表达式都支持占有量词。对于那些味道,您可以使用原子组实现完全相同的结果。
基本上,代替X*+,写成(?>X*)。重要的是要注意,量化的标记X和量化器都在原子组内。即使X是一个组,您仍然需要在其周围放置一个额外的原子组以实现相同的效果。(?:a|b)*+等同于(?>(?:a|b)*),但不等于(?>a|b)*。后者是一个有效的正则表达式,但在作为较大正则表达式的一部分使用时,它将没有相同的效果。

1
如果你看一下这个正则表达式网页的页面,你会注意到在表格中"x++(?>x+)是相同的"。
唯一指出的区别是: 是一个有限但语法更清晰的替代原子分组。
所以,它不像原子分组那么受欢迎,但可以被认为更加清洁。

顺便提一下,原子组合与仅限一次子模式是同义词。只是称呼方式不同而已。 - Jerry

1
请注意,从回溯的角度来看,(?>X+)X++并不完全相同。因为在括号内,正则表达式引擎有可能回溯,因此正则表达式引擎始终记录原子组内的回溯位置(但在括号关闭后会忘记它们),这当然不适用于占有量词。例如:
考虑字符串aaaabbbb (?>a+)ab作为a++ab将失败,因为正则表达式引擎在原子组关闭后无法回溯。
但是 (?>a+ab)将成功,因为回溯位置始终记录在原子组中。 (?:a+|ab)+(?<!a)b将成功,但(?>a+|ab)+(?<!a)b将失败,因为每次重复之间都会关闭括号。
结论:确切的(?>X+)的同义词不是X++,而是(?:X+){1}+

+1 讲解得非常清楚。只是好奇为什么我们需要在 (?:X+){1}+ 中使用 {1},难道我们不能使用 (?:X+)+ 吗? - anubhava
@anubhava:谢谢,不过{1}+只是一种人为的方法,用于使非捕获组成为原子组(仅用于解释目的,完全没有用处,因为有原子组)。 (?:X+)+将重复非捕获组(这不是我在示例中要寻找的),而且根本不是原子或占有的。 - Casimir et Hippolyte

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