匹配可选组

时间:2015-08-11 23:07:33

标签: java regex

使用以下代码:

    Pattern pattern = Pattern.compile("((foo) (bar)?)|((foo) (baz)?)");

    Matcher matcher = pattern.matcher("foo baz");

    if(matcher.find()){
        for(int i=1; i<=matcher.groupCount(); i++){
            System.out.println(matcher.group(i));
        }
    } 

结果是:

foo 
foo
null
null
null
null

我希望:

null
null
null
foo baz
foo
baz

如何匹配第二项?

我想匹配完整的&#34; foo baz&#34;如果可能,否则匹配&#34; foo&#34;

2 个答案:

答案 0 :(得分:3)

您的正则表达式按预期运行:您的输入"foo baz"((foo) (bar)?)匹配 - 至少"foo "部分匹配。通常,正则表达式更喜欢最长模式(贪婪)定义第一个(从左到右),而"foo "匹配优于"foo baz"

如果您想确保整个表达式匹配,则需要^$

Pattern pattern = Pattern.compile("^((foo) (bar)?)$|^((foo) (baz)?)$");

答案 1 :(得分:2)

此问题与a|aa非常相似,aa永远无法匹配任何内容,因为左侧网站a

  • 将首先执行
  • 并且可以匹配所有单a(即使是"aa"中的那个)

您无法更改正则表达式的机制并强制尝试匹配所有regex1|regex2|regex3个案,因为

  • 会降低其性能,
  • 可能更重要的是,如果regex1 regex2这两个案例匹配怎么办?例如,如果正则表达式为a|aa且我们有aaaa之类的数据,我们应该从下一场比赛开始搜索,a:aaaaa:aa:代表regex cursor)?

因此,您可以重新设置正则表达式,以确保它能够完全匹配每个案例,并在更常见的匹配之前进行更精确的匹配,例如

(foo bar)|(foo baz)|(foo)

您也可以将其重写为

(foo) (?:(bar)|(baz))?