正则表达式定义
Regular expression DEFINE
谁能解释为什么这个正则表达式
/(?(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
还有我怎样才能完全匹配它,同时仍然对每个部分都有单独的定义
当你引用一个子模式时,与这个子模式匹配的子串变成原子的。这就是为什么您的第一个模式仅获得 "Garantie" 的原因。对于 "Vor-Ort-" 中的每个位置,(?&alnum)
匹配所有字符,直到 "Garantie" 结束,但是一旦进入 (?<warranty_word> ...)
的地面,正则表达式引擎就无法回溯,因为 (?&alnum)
是原子的。
注意:顺便说一句,当你必须处理 ascii 范围之外的字符时,你必须使用 u 修饰符,否则你的模式和你的目标字符串将被视为连续的单字节字符而不是 utf8编码字符串:
# ö is encoded with C3 B6
var_dump(preg_match('~[ö]~', "\xC3"));
# int(1)
var_dump(preg_match('~[ö]~u', "\xC3"));
# bool(false)
使用此修饰符,您可以从角色中删除 Ä、Ö 和 Ü 类,因为您的模式不区分大小写。
非常有趣的问题。经过一番挖掘,我想我在 PCRE documentation 中找到了答案(将这些子模式称为 "subroutine calls"):
All subroutine calls, whether recursive or not, are always treated as
atomic groups. That is, once a subroutine has matched some of the
subject string, it is never re-entered, even if it contains untried
alternatives
因此,这意味着,在您的第一个模式中,一旦 (?&alnum)
匹配 任何东西,它就会被使用并丢弃。在 3 Jahre Vor-Ort-Garantie
的示例数据中,它将匹配数字 3。然后匹配的其余部分将失败,并且它会在不包括 (?&alnum)
的情况下重试(因为这是可选的),但它不会再次尝试该子模式。
如果支持的话,您可以在您的编程语言中使用变量插值。例如,在 Perl 中:
my $alnum = "[a-zäöüßÖÜÄ0-9-]+";
my $warranty_word = "(?:$alnum)?garantie[*]?";
if ($string =~ /$warranty_word/)
{
...
}
这几乎可以如您所愿地工作,而且它还为您提供了额外的灵活性,因为子模式可以在不同的地方使用。但它在其他语言中可能会变得混乱,具体取决于字符串插值机制。
谁能解释为什么这个正则表达式
/(?(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
还有我怎样才能完全匹配它,同时仍然对每个部分都有单独的定义
当你引用一个子模式时,与这个子模式匹配的子串变成原子的。这就是为什么您的第一个模式仅获得 "Garantie" 的原因。对于 "Vor-Ort-" 中的每个位置,(?&alnum)
匹配所有字符,直到 "Garantie" 结束,但是一旦进入 (?<warranty_word> ...)
的地面,正则表达式引擎就无法回溯,因为 (?&alnum)
是原子的。
注意:顺便说一句,当你必须处理 ascii 范围之外的字符时,你必须使用 u 修饰符,否则你的模式和你的目标字符串将被视为连续的单字节字符而不是 utf8编码字符串:
# ö is encoded with C3 B6
var_dump(preg_match('~[ö]~', "\xC3"));
# int(1)
var_dump(preg_match('~[ö]~u', "\xC3"));
# bool(false)
使用此修饰符,您可以从角色中删除 Ä、Ö 和 Ü 类,因为您的模式不区分大小写。
非常有趣的问题。经过一番挖掘,我想我在 PCRE documentation 中找到了答案(将这些子模式称为 "subroutine calls"):
All subroutine calls, whether recursive or not, are always treated as atomic groups. That is, once a subroutine has matched some of the subject string, it is never re-entered, even if it contains untried alternatives
因此,这意味着,在您的第一个模式中,一旦 (?&alnum)
匹配 任何东西,它就会被使用并丢弃。在 3 Jahre Vor-Ort-Garantie
的示例数据中,它将匹配数字 3。然后匹配的其余部分将失败,并且它会在不包括 (?&alnum)
的情况下重试(因为这是可选的),但它不会再次尝试该子模式。
如果支持的话,您可以在您的编程语言中使用变量插值。例如,在 Perl 中:
my $alnum = "[a-zäöüßÖÜÄ0-9-]+";
my $warranty_word = "(?:$alnum)?garantie[*]?";
if ($string =~ /$warranty_word/)
{
...
}
这几乎可以如您所愿地工作,而且它还为您提供了额外的灵活性,因为子模式可以在不同的地方使用。但它在其他语言中可能会变得混乱,具体取决于字符串插值机制。