正则表达式DEFINE

时间:2016-10-25 10:33:50

标签: regex pcre

有人可以解释为什么这个正则表达式

/(?(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

以及如何完全匹配它,同时仍然对每个部分有单独的定义

2 个答案:

答案 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/)
{
    ...
}

这可以随心所欲地工作,并且它还为您提供了额外的灵活性,因为子模式可以在不同的地方使用。但是在其他语言中它可能会变得混乱,这取决于字符串插值机制。