在Java中查找多个正则表达式匹配项,禁止不匹配项

时间:2020-01-20 04:03:48

标签: java regex regex-group

我有一个Java Pattern,例如\s+(foo|bar),可以在空格后找到foobar的所有匹配项。使用匹配组,我可以提取实际匹配的文本。

Pattern pattern=Pattern.compile("\\s+(foo|bar)");
Matcher matcher = pattern.match(someText);
while(matcher.find()) {
  String value = matcher.group(1);
  ...
}

这适用于类似foo foo bar的字符串(请注意前面的空格),但它也可以匹配类似foo foo bad的字符串。如何阻止匹配器匹配不匹配的后续字符运行,或者检测到跳过了字符或没有剩余的字符了?换句话说,我希望整个字符串被匹配为与模式匹配的一系列后续字符串。我怎么能保证呢?

这里的重点是继续通过字符串查找匹配项。我可以轻松地拆分字符串,然后执行其他比较,但是我不希望多次正则表达式传递,数组/列表创建等产生开销。

1 个答案:

答案 0 :(得分:2)

\G前缀正则表达式。 Pattern的Javadoc说:

\G-上一场比赛的结束

当然,在第一场比赛中,“上一场比赛的结束”是输入的开始。

这确保从输入的开头开始,所有正则表达式匹配都将是连续的。并不意味着正则表达式将到达输入的末尾,您必须自己检查一下。

示例

public static void main(String[] args) {
    test("abc");
    test(" foo foo bar");
    test(" foo foo bad");
    test(" foo bad foo");
}
static void test(String input) {
    System.out.println("'" + input + "'");
    int lastEnd = 0;
    Matcher m = Pattern.compile("\\G\\s+(foo|bar)").matcher(input);
    while (m.find()) {
        System.out.printf("  g0='%s' (%d-%d), g1='%s' (%d-%d)%n",
                          m.group(), m.start(), m.end(),
                          m.group(1), m.start(1), m.end(1));
        lastEnd = m.end();
    }
    if (lastEnd == input.length())
        System.out.println("  OK");
    else
        System.out.println("  Incomplete: Last match ended at " + lastEnd);
}

输出

'abc'
  Incomplete: Last match ended at 0
' foo foo bar'
  g0=' foo' (0-4), g1='foo' (1-4)
  g0=' foo' (4-8), g1='foo' (5-8)
  g0=' bar' (8-12), g1='bar' (9-12)
  OK
' foo foo bad'
  g0=' foo' (0-4), g1='foo' (1-4)
  g0=' foo' (4-8), g1='foo' (5-8)
  Incomplete: Last match ended at 8
' foo bad foo'
  g0=' foo' (0-4), g1='foo' (1-4)
  Incomplete: Last match ended at 4

为了进行比较,在正则表达式中没有\G时,该代码的输出为:

'abc'
  Incomplete: Last match ended at 0
' foo foo bar'
  g0=' foo' (0-4), g1='foo' (1-4)
  g0=' foo' (4-8), g1='foo' (5-8)
  g0=' bar' (8-12), g1='bar' (9-12)
  OK
' foo foo bad'
  g0=' foo' (0-4), g1='foo' (1-4)
  g0=' foo' (4-8), g1='foo' (5-8)
  Incomplete: Last match ended at 8
' foo bad foo'
  g0=' foo' (0-4), g1='foo' (1-4)
  g0=' foo' (8-12), g1='foo' (9-12)
  OK

如您所见,最后一个示例将无法检测到跳过了文本bad