2

使用 PCRE v8.42,我试图将一个正则表达式抽象为一个命名的子例程,但是当它在一个子例程中时,它的行为似乎有所不同。

这输出10/

echo '10/' | pcregrep '(?:0?[1-9]|1[0-2])\/' 

这什么也不输出:

echo '10/' | pcregrep '(?(DEFINE)(?<MONTHNUM>(?:0?[1-9]|1[0-2])))(?&MONTHNUM)\/'

这两个正则表达式不等价吗?

4

1 回答 1

1

在10.30 之前的 PCRE2 版本中,所有子例程调用始终被视为原子组。您的(?(DEFINE)(?<MONTHNUM>(?:0?[1-9]|1[0-2])))(?&MONTHNUM)\/正则表达式实际上等于(?>0?[1-9]|1[0-2])\/. 请参阅此正则表达式演示,其中10/与预期不匹配。

没有匹配,因为0?[1-9]匹配1in10/并且由于不允许回溯,第二个替代方案没有经过测试(“输入”),整个匹配失败,因为没有/after 1

您需要确保较长的替代方案首先出现:

(?(DEFINE)(?<MONTHNUM>(?:1[0-2]|0?[1-9])))(?&MONTHNUM)/

请参阅正则表达式演示。请注意,在pcregrep模式中,您不需要 escape /

或者,您可以使用 PCRE2 v10.30 或更高版本。

于 2020-12-29T17:54:19.820 回答