11

正则表达式原子组是分布的吗?

(?>A?B?)总是等价于(?>A?)(?>B?)?

如果不是,请提供一个反例。

4

2 回答 2

2

一般原子团

  1. 原子组(?>regex1|regex2|regex3)只接受其中的第一个成功匹配。换句话说,它不允许回溯。

  2. 正则表达式从左到右进行评估,因此您可以表达您想要匹配的顺序。引擎从第一个位置开始,尝试成功匹配,必要时回溯。如果通过表达式的任何路径将导致成功匹配,那么它将在该位置匹配。

  3. 原子团不是分配性的。考虑评估这些模式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?)。因此,如果我的推理是正确的,对于这种特殊情况,多个可选原子组的匹配将与具有两个可选组件的单个原子组相同。

于 2012-05-31T02:47:49.830 回答
1

由于您没有指定,我假设您指的是 Perl 正则表达式,因为我没有看到(?>)任何其他语言的分组运算符。

考虑以下:

ra = 'A?'
rb = 'B?'

/(?>${ra} ${rb})/x是一样的/(?>${ra})(?>${rb})/x

在这种情况下,是的,无论哪种方式都可以;但是,由于禁用了回溯,因此和(?>)的某些其他值不是这种情况。rarb

例如,给定:

ra = 'A*'
rb = 'AB*'

/(?>${ra} ${rb})/x!= /(?>${ra})(?>${rb})/x

在后者中, rb 永远无法匹配,因为 ra 会消耗整个 A 序列,并且不允许回溯。请注意,如果我们用作分组运算符,这将起作用。(?:)另请注意,如果我们使用 capture groups (),那么匹配将是相同的,但副作用(分配给\1, \2, ...)会有所不同。

于 2012-05-31T02:56:34.033 回答