如何解决为什么这个正则表达式在 PCRE (PHP < 7.3) 中失败,但在 PCRE2 (PHP >= 7.3) 中有效
正则表达式:
/(?<nn>(?!und)[^\/,&;]+)(?:,\s?+)(?<vn>(?1))(?:\/|&|;|und|$)\s?/
应该使用 preg_match_all
nn(1): Oidtmann-van Beek
vn(1): Jeanne
nn(2): Oidtmann
vn(2): Peter
关于示例字符串 Oidtmann-van Beek,Jeanne und Oidtmann,Peter
这适用于 PCRE2 (PHP >= 7.3)。
但不是 PHP
https://regex101.com/r/zotHZN/1/
解决方法
您没有通过 PCRE 获得预期的输出,因为 (?1)
正则表达式子例程是原子的,并且其模式无法回溯。
见"Differences in recursion processing between PCRE2 and Perl":
在 10.30 版本之前,PCRE2 中的递归处理与 Perl 的不同之处在于递归子程序调用始终被视为原子组。也就是说,一旦它匹配了某些主题字符串,就永远不会重新输入,即使它包含未尝试的替代方案并且随后出现匹配失败。 (历史记录:PCRE 在 Perl 之前实现了递归。)
从 10.30 版开始,递归子例程调用不再被视为原子调用。也就是说,如果模式稍后出现匹配失败,则可以重新输入它们以尝试未使用的替代方案。这现在与 Perl 的工作方式兼容。如果您希望子程序调用具有原子性,则必须将其显式包含在原子组中。
所以,解决方案是使用模式本身,而不是子程序:
/(?<nn>(?!und)[^\/,&;]+),\s?+(?<vn>(?!und)[^\/,&;]+)(?:\/|&|;|und|$)\s?/
注意我用 (?:,\s?+)
替换了 \s?+
,因为这里的非捕获组是多余的。
我认为像 /\b(?<nn>(?!und\b)\w+(?:[-'\s]+(?!und\b)\w+)*),\s?(?<vn>(?&nn))\b/u
这样更精确的模式在这里会更好。见this regex demo。它不需要任何回溯,因为 \w+(?:[-'\s]+(?!und\b)\w+)*
部分不与 ,\s?
模式重叠。
版权声明:本文内容由互联网用户自发贡献,该文观点与技术仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 dio@foxmail.com 举报,一经查实,本站将立刻删除。