来自Java 6Pattern文档:
特殊结构(非捕获)
(?:
X)
作为非捕获组的X…
(?>
X)
作为独立的、非捕获的组的X
(?:X)
和(?>X)
之间有什么区别?在这个上下文中,“独立”是什么意思?
这意味着分组是原子的,它会丢弃匹配组的回溯信息。因此,这个表达式是占有性的;即使这样做是整个正则表达式成功的唯一方式,它也不会后退。在这个意义上,它是“独立的”,因为它不通过回溯与正则表达式的其他元素合作以确保匹配。
a(bc|b)c
(捕获分组)匹配abcc和abc。正则表达式a(?>bc|b)c
(原子分组)匹配abcc但不匹配abc。a
与a匹配,将bc
与bc匹配,然后在字符串末尾失败地尝试将c
与字符匹配。它们的路径在这里分叉。使用捕获分组的正则表达式记住了一个备用位置来进行选择。该组将放弃匹配,b
然后匹配b,c
匹配c。找到匹配项!bc
后退出了原子分组。此时,组内标记的所有备用位置都将被丢弃。在这个例子中,备选项在字符串的第二个位置尝试b
的选择将被丢弃。结果,当c
失败时,正则表达式引擎没有其他可尝试的方案。foo(?>(co)*)co
,那么它永远不会匹配。我相信有实际的例子可以说明这个正则表达式的用途,请参考O'Reilly的书籍。(?>X?)
等同于 (?:X)?+
,(?>X*)
等同于 (?:X)*+
,(?>X+)
等同于 (?:X)++
。
除了 X 必须是一个非捕获组之外,前面的等式可以简化为:
(?>X?)
等同于 X?+
,(?>X*)
等同于 X*+
,(?>X+)
等同于 X++
。
independent
一词非常重要。它们并不完全相同,因为(?>X)
在部分匹配失败时不会进行任何回溯,所以使用其中一个匹配的某些内容将无法使用另一个匹配。 erickson 链接的文章对我很有帮助。 - xdhmooreX
本身是原子时才有效,而在文档中并不一定是这种情况——有时候X必须是一个原子(例如X?+
),有时候则不是(例如(X)
)。具体来说,(?>X?)
仅当X是原子时等于X?+
:(?>foo?)
不等同于(?:foo)?+
。 - Jelaby