我运行了以下代码:
public static void main(String[] args) {
Pattern pattern = Pattern.compile("(asd|asdf).*");
Pattern pattern2 = Pattern.compile("(asdf|asd).*");
Matcher m = pattern.matcher("asdf");
Matcher m2 = pattern2.matcher("asdf");
if (m.matches()) {
System.out.println(m.group(1));
}
if (m2.matches()) {
System.out.println(m2.group(1));
}
}
我得到以下输出:
ASD
ASDF
似乎在两者匹配的情况下选择OR组的左侧。但是,我无法找到记录此行为。有谁知道行为是否已定义?
答案 0 :(得分:2)
在非POSIX正则表达式中(如在Java中,作为The Pattern
engine performs traditional NFA-based matching with ordered alternation as occurs in Perl 5),第一个备选方案是匹配的。在POSIX中,最长的替代方案是匹配的。
查看Perl help关于更改的内容:
要匹配
dog
或cat
,我们会形成正则表达式dog|cat
。和以前一样,Perl会尝试匹配字符串中最早可能的点的正则表达式。在每个角色位置,Perl将首先尝试匹配第一个替代dog
。如果dog
不匹配,Perl将尝试下一个替代cat
。如果cat
也不匹配,则匹配失败,Perl移动到字符串中的下一个位置。
请参阅描述符合NFA的交替行为的Alternation with The Vertical Bar or Pipe Symbol at regular-expressions.info:
备选方案的顺序很重要。假设您要使用正则表达式来匹配编程语言中的函数名称列表:
Get
,GetValue
,{{ 1}}或Set
。显而易见的解决方案是SetValue
。正则表达式引擎从正则表达式中的第一个标记
Get|GetValue|Set|SetValue
开始,并在字符串中的第一个字符G
处启动。比赛失败了。但是,正则表达式引擎在开始之前研究了整个正则表达式。所以它知道这个正则表达式使用了交替,并且整个正则表达式还没有失败。所以它继续第二个选项,是正则表达式中的第二个S
。比赛再次失败。下一个标记是正则表达式中的第一个G
。匹配成功,引擎继续使用字符串中的下一个字符,以及正则表达式中的下一个标记。正则表达式中的下一个标记是刚刚成功匹配的S
之后的e
。S
匹配e
。下一个标记e
与t
匹配。此时,交替中的第三个选项已成功匹配。由于正则表达式引擎非常渴望,因此只要其中一个选项具有,就会认为整个交替已成功匹配。在此示例中,在交替之外的正则表达式中没有其他标记,因此整个正则表达式已成功匹配
t
中的Set
。
然后:
但 POSIX标准确实要求返回最长的匹配,即使使用正则表达式引擎也是如此。这样的引擎不能急于求成。即使在找到匹配项之后,它也必须继续尝试所有替代方案,以便找到最长的一个。
但是,如果严格定义任何一方的上下文,则替代方案的顺序可能无关紧要。如果您使用锚点SetValue
来匹配完整字符串,则只能获得与正确替代字符对应的锚点。