使用 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)\/'
这两个正则表达式不等价吗?
在10.30 之前的 PCRE2 版本中,所有子例程调用始终被视为原子组。您的(?(DEFINE)(?<MONTHNUM>(?:0?[1-9]|1[0-2])))(?&MONTHNUM)\/
正则表达式实际上等于(?>0?[1-9]|1[0-2])\/
. 请参阅此正则表达式演示,其中10/
与预期不匹配。
没有匹配,因为0?[1-9]
匹配1
in10/
并且由于不允许回溯,第二个替代方案没有经过测试(“输入”),整个匹配失败,因为没有/
after 1
。
您需要确保较长的替代方案首先出现:
(?(DEFINE)(?<MONTHNUM>(?:1[0-2]|0?[1-9])))(?&MONTHNUM)/
请参阅正则表达式演示。请注意,在pcregrep
模式中,您不需要 escape /
。
或者,您可以使用 PCRE2 v10.30 或更高版本。