Java正则表达式,无法正确捕获最后一组

时间:2017-05-11 12:20:50

标签: java regex

我试图用 Java 正则表达式

解析几个简单的行
[txt1] [txt2] [txt3] /some/long/path?params=1,2,3
[txt1] [txt2] [txt3] /path/
[txt1] [txt2] [txt3] /

我的正则表达式字符串是^\[(.*?)\] \[(.*?)\] \[(.*?)\] (/.*)(\?.*)

我正在努力捕捉最后一组 - 用我的正则表达式,只有第一行匹配模式而不是其他两行。如果我将我的正则表达式更改为^\[(.*?)\] \[(.*?)\] \[(.*?)\] (/.*)(\?.*)?,则所有3行都匹配,但第一行未成功捕获(我只获得1组/some/long/path?params=1,2,3而不是2 /some/long/path和{{ 1}})。

如何编写此正则表达式,以便所有行都有5个匹配的组?

2 个答案:

答案 0 :(得分:3)

最好在正则表达式中使用否定字符类来获得正确性和更好的性能:

^\[([^]]*)\] \[([^]]*)\] \[([^]]*)\] (/[^?]*)(\?.*)?$

RegEx Demo

使用否定字符类,您不需要使用任何延迟量词,因为[^?]*将匹配任何不是?的字符中的0个或更多

Code Demo

答案 1 :(得分:1)

让你最后但只有一个.*懒惰,让最后一个捕获组成为可选项,然后附加$,字符串锚点结束:

^\[(.*?)] \[(.*?)] \[(.*?)] (/.*?)(\?.*)?$
                                ^       ^^

请参阅regex demo

  • .*?群组中的(/.*?)应该是懒惰的,因为我们需要允许后续群组填充尽可能多的字符
  • (\?.*)? - 必须是可选的,因为文字可能不存在
  • $是必要的,因为前两组是可选的,因此字符串末尾的文本不会匹配。这样,我们需要正则表达式引擎来抓住剩下的部分。

查看Java demo

Pattern pattern = Pattern.compile("^\\[(.*?)] \\[(.*?)] \\[(.*?)] (/.*?)(\\?.*)?$");
String[] ss = { "[txt1] [txt2] [txt3] /some/long/path?params=1,2,3", "[txt1] [txt2] [txt3] /path/", "[txt1] [txt2] [txt3] /"};
for (String s: ss) {
    Matcher matcher = pattern.matcher(s);
    while (matcher.find()){
        System.out.println("Next match for \"" + s + "\"" ); 
        System.out.println(matcher.group(1));
        System.out.println(matcher.group(2)); 
        System.out.println(matcher.group(3)); 
        System.out.println(matcher.group(4)); 
        System.out.println(matcher.group(5)); 
    } 
}

输出:

Next match for "[txt1] [txt2] [txt3] /some/long/path?params=1,2,3"
txt1
txt2
txt3
/some/long/path
?params=1,2,3
Next match for "[txt1] [txt2] [txt3] /path/"
txt1
txt2
txt3
/path/
null
Next match for "[txt1] [txt2] [txt3] /"
txt1
txt2
txt3
/
null