正则表达式原子组是分布的吗?
即(?>A?B?)
总是等价于(?>A?)(?>B?)
?
如果不是,请提供一个反例。
一般原子团
原子组(?>regex1|regex2|regex3)
只接受其中的第一个成功匹配。换句话说,它不允许回溯。
正则表达式从左到右进行评估,因此您可以表达您想要匹配的顺序。引擎从第一个位置开始,尝试成功匹配,必要时回溯。如果通过表达式的任何路径将导致成功匹配,那么它将在该位置匹配。
原子团不是分配性的。考虑评估这些模式ABC
:(
(?>(AB?))(?>(BC))
不匹配)和(?>(AB?)(BC))
(匹配ABC
)。
具有所有可选组件的原子组
但是,两个部分都是可选的情况可能会有所不同。
考虑具有 2 个贪婪可选部分 A 和 B ((A)?
和(B)?
) 的原子组。在任何位置,如果A
匹配,它可以继续评估 optional B
。否则,如果A
不匹配,那也没关系,因为它是可选的。因此,(A)?
匹配任何位置。相同的逻辑适用于可选的B
. 剩下的问题是回溯是否有任何差异。
对于所有可选部分 ( (?>A?B?)
),由于每个部分始终匹配,因此没有理由在原子组内回溯,因此它将始终匹配。然后,由于它在一个原子组中,所以它被禁止回溯。
在单独的原子组 ( (?>A?)(?>B?)
) 的情况下,每个部分始终匹配,并且在任何一种情况下都禁止引擎回溯。这意味着结果将是相同的。
重申一下,引擎只能使用 in 中的第一个可能匹配(?>A?)(?>B?)
,这将始终与 in 中的第一个可能匹配相同(?>A?B?)
。因此,如果我的推理是正确的,对于这种特殊情况,多个可选原子组的匹配将与具有两个可选组件的单个原子组相同。
由于您没有指定,我假设您指的是 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 序列,并且不允许回溯。请注意,如果我们用作分组运算符,这将起作用。(?:)
另请注意,如果我们使用 capture groups ()
,那么匹配将是相同的,但副作用(分配给\1
, \2
, ...)会有所不同。