正则表达式原子组是分配的吗?
即。 (?>A?B?)
始终等同于(?>A?)(?>B?)
?
如果没有,请提供一个反例。
答案 0 :(得分:2)
一般的原子组
原子组(?>regex1|regex2|regex3)
仅获取其中的第一个成功匹配。换句话说,它不允许回溯。
正则表达式从左到右进行评估,因此您表达了您想要匹配的顺序。发动机从第一个位置开始,试图成功匹配,必要时回溯。如果通过表达式的任何路径将导致成功匹配,那么它将在该位置匹配。
原子团不是分配的。考虑在ABC
上评估的这些模式:
(?>(AB?))(?>(BC))
(不匹配)和(?>(AB?)(BC))
(匹配ABC
)。
包含所有可选组件的原子组
但是,两个部分都是可选的情况可能不同。
考虑具有2个贪婪的可选部分A和B((A)?
和(B)?
)的原子组。在任何位置,如果A
匹配,它可以继续评估可选的B
。否则,如果A
不匹配,那也没关系,因为它是可选的。因此,(A)?
匹配任何位置。相同的逻辑适用于可选的B
。剩下的问题是回溯是否会有任何差异。
对于所有可选部分((?>A?B?)
),由于每个部分始终匹配,因此没有理由在原子组内回溯,因此它将始终匹配。然后,由于它处于原子组中,因此禁止回溯。
对于单独的原子组((?>A?)(?>B?)
),每个部分始终匹配,并且在任何一种情况下都禁止引擎回溯。这意味着结果将是相同的。
重申一下,引擎只能使用(?>A?)(?>B?)
中的第一个匹配项,这与(?>A?B?)
中第一个可能匹配的匹配项始终相同。因此,如果我的推理是正确的,对于特殊情况,匹配将是多个可选原子组的相同,作为具有两个可选组件的单个原子组。
答案 1 :(得分:1)
由于您没有指定,我假设您指的是Perl正则表达式,因为我没有看到任何其他语言的(?>)
分组运算符。
请考虑以下事项:
ra = 'A?'
rb = 'B?'
/(?>${ra} ${rb})/x
与/(?>${ra})(?>${rb})/x
相同。
在这种情况下,是的,它可以正常工作;但是,由于(?>)
禁用了回溯功能,因此ra
和rb
的某些其他值并非如此。
例如,给定:
ra = 'A*'
rb = 'AB*'
/(?>${ra} ${rb})/x
!= /(?>${ra})(?>${rb})/x
。
在后者中,rb永远不会匹配,因为ra将消耗整个A序列,并且不允许回溯。请注意,如果我们使用(?:)
作为分组运算符,则将工作。另请注意,如果我们使用了捕获组()
,那么匹配将是相同的,但副作用(分配给\1
, \2
,...)会有所不同。