有人可以解释为什么这个正则表达式
/(?(DEFINE)
(?<alnum> [a-zäöüßÖÜÄ0-9-]+ )
(?<warranty_word> (?&alnum)?garantie[*]?)
)
(?&warranty_word)/six
仅匹配 Vor-Ort-Garantie 中的 Garantie ,但此其他 https://regex101.com/r/oJKV1Q/1
/(?(DEFINE)
(?<warranty_word> ([a-zäöüßÖÜÄ0-9-]+)?garantie[*]?)
)
(?&warranty_word)/six
完全匹配 Vor-Ort-Garantie https://regex101.com/r/axvJmA/1
以及如何完全匹配它,同时仍然对每个部分有单独的定义
答案 0 :(得分:2)
当您引用子模式时,此子模式匹配的子字符串将变为原子。这就是为什么你只获得第一个模式的“Garantie”。对于“Vor-Ort-”中的每个位置,(?&alnum)
匹配所有字符,直到“Garantie”结束,但一旦在(?<warranty_word> ...)
的基础上,正则表达式引擎无法回溯{{1}是原子的。
注意:另外,当你必须处理ascii范围之外的字符时,必须使用u修饰符,否则你的模式和目标字符串被视为一系列单字节字符而不是utf8编码的字符串:
(?&alnum)
使用此修饰符,您可以从字符类中删除Ä,Ö和Ü,因为您的模式不区分大小写。
答案 1 :(得分:2)
非常有趣的问题。经过一番挖掘,我想我在PCRE documentation中找到了答案(将这些子模式称为&#34;子程序调用&#34;)
所有子程序调用(无论是否递归)始终被视为 原子团。也就是说,一旦子程序匹配了一些 主题字符串,它永远不会重新输入,即使它包含未经验证的 替代
所以,这意味着,在您的第一个模式中,只要(?&alnum)
匹配任何内容,就会使用并丢弃它。在3 Jahre Vor-Ort-Garantie
的示例数据中,它将匹配数字3.然后匹配的其余部分将失败,并且它将再次尝试而不包括(?&alnum)
(因为这是可选的),但它不会#39 ;再次尝试该子模式。
如果支持,您可以在编程语言中使用变量插值。例如,在Perl中:
my $alnum = "[a-zäöüßÖÜÄ0-9-]+";
my $warranty_word = "(?:$alnum)?garantie[*]?";
if ($string =~ /$warranty_word/)
{
...
}
这可以随心所欲地工作,并且它还为您提供了额外的灵活性,因为子模式可以在不同的地方使用。但是在其他语言中它可能会变得混乱,这取决于字符串插值机制。