当一个OR正则表达式组的两半匹配时,是否定义了哪个将被选择?

时间:2016-01-22 11:51:43

标签: java regex

我运行了以下代码:

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组的左侧。但是,我无法找到记录此行为。有谁知道行为是否已定义?

1 个答案:

答案 0 :(得分:2)

在非POSIX正则表达式中(如在Java中,作为The Pattern engine performs traditional NFA-based matching with ordered alternation as occurs in Perl 5),第一个备选方案是匹配的。在POSIX中,最长的替代方案是匹配的。

查看Perl help关于更改的内容:

  

要匹配dogcat,我们会形成正则表达式dog|cat。和以前一样,Perl会尝试匹配字符串中最早可能的点的正则表达式。在每个角色位置,Perl将首先尝试匹配第一个替代dog。如果dog不匹配,Perl将尝试下一个替代cat。如果cat也不匹配,则匹配失败,Perl移动到字符串中的下一个位置。

请参阅描述符合NFA的交替行为的Alternation with The Vertical Bar or Pipe Symbol at regular-expressions.info

  

备选方案的顺序很重要。假设您要使用正则表达式来匹配编程语言中的函数名称列表:GetGetValue,{{ 1}}或Set。显而易见的解决方案是SetValue

     

正则表达式引擎从正则表达式中的第一个标记Get|GetValue|Set|SetValue开始,并在字符串中的第一个字符G处启动。比赛失败了。但是,正则表达式引擎在开始之前研究了整个正则表达式。所以它知道这个正则表达式使用了交替,并且整个正则表达式还没有失败。所以它继续第二个选项,是正则表达式中的第二个S。比赛再次失败。下一个标记是正则表达式中的第一个G。匹配成功,引擎继续使用字符串中的下一个字符,以及正则表达式中的下一个标记。正则表达式中的下一个标记是刚刚成功匹配的S之后的eS匹配e。下一个标记et匹配。

     

此时,交替中的第三个选项已成功匹配。由于正则表达式引擎非常渴望,因此只要其中一个选项具有,就会认为整个交替已成功匹配。在此示例中,在交替之外的正则表达式中没有其他标记,因此整个正则表达式已成功匹配t中的Set

然后:

  

POSIX标准确实要求返回最长的匹配,即使使用正则表达式引擎也是如此。这样的引擎不能急于求成。即使在找到匹配项之后,它也必须继续尝试所有替代方案,以便找到最长的一个。

但是,如果严格定义任何一方的上下文,则替代方案的顺序可能无关紧要。如果您使用锚点SetValue来匹配完整字符串,则只能获得与正确替代字符对应的锚点。