正则表达式匹配最短匹配而不是最长匹配

时间:2016-08-12 23:17:12

标签: java regex

我正在尝试编写正则表达式,但在某些情况下无法使其正常工作。这是正则表达式

(\/[ABCGIKLNPRSUV])?(\/RC-[A-Z0-9]{2,6})?

匹配可以是以下之一

  • / R / RC-ABC123
  • / R
  • / RC-ABC123

上述正则表达式适用于/ R和/ R / RC-ABC123但不适用于/ RC-ABC123。对于/ RC-ABC123,它保持与第一组而不是第二组匹配,并且仅将/ R作为匹配组件。

如何使其适用于所有情况。此外,上述表达仅是完整表达的一部分,即在RC-ABC123之后可能存在另一(第三)组。但是想先让这两个小组合作。

更新 ?? ??似乎在regex101中工作,但在java中不起作用。我使用以下代码

获得2组但使用/ R / RC-ABC123的空值
Pattern pattern = Pattern.compile("(/[A-Z])??(/RC-[A-Z0-9]{2,6})?");
    Matcher matcher = pattern.matcher("/R/RC-ABC12345");
    if(matcher.find()) {
        for(int i=1; i<= matcher.groupCount(); i++) {
            System.out.println("Group("+i+") = " + matcher.group(i));
        }
    }else {
        System.out.println("Pattern does not match");
    }

2 个答案:

答案 0 :(得分:0)

使用??使第一个可选组非贪婪,因此如果可以选择,则更愿意匹配第二个组。

(/[ABCGIKLNPRSUV])??(/RC-[A-Z0-9]{2,6})?

DEMO

答案 1 :(得分:0)

您需要确保R取自第一个可选组字符类,因为它允许第一个组匹配与第二个组相同的位置。

您可以在第一个捕获组中创建一个非捕获子组来处理这种情况,并使用负向前瞻“调整”R分支,以便它只匹配R s未跟随C-,然后是2到6个大写ASCII字母或数字:

Pattern pattern = Pattern.compile("(/(?:R(?!C-[A-Z0-9]{2,6})|[ABCGIKLNPSUV]))?(/RC-[A-Z0-9]{2,6})?");

Java demo。测试结果:

/RC-ABC123    ->  { Group(1) = null, Group(2) = /RC-ABC123 }
/R/RC-ABC123  ->  { Group(1) = /R, Group(2) = /RC-ABC123 }
/R            ->  { Group(1) = /R, Group(2) = null }
/S/RC-ABC123  ->  { Group(1) = /S, Group(2) = /RC-ABC123 }

模式详情

  • (/(?:R(?!C-[A-Z0-9]{2,6})|[ABCGIKLNPSUV]))? - 可选第2组:
    • / - 正斜杠
    • (?:R(?!C-[A-Z0-9]{2,6})|[ABCGIKLNPSUV]) - 非捕获组中的2个替代方案:
      • R(?!C-[A-Z0-9]{2,6}) - R未跟随C-,然后是2到6个大写ASCII字母或数字
      • | - 或
      • [ABCGIKLNPSUV] - 其中1封信件
  • (/RC-[A-Z0-9]{2,6})? - 可选第2组:
    • /RC- - 文字子串/RC-
    • [A-Z0-9]{2,6} - 2到6个大写ASCII字母或数字。