我试图用 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个匹配的组?
答案 0 :(得分:3)
最好在正则表达式中使用否定字符类来获得正确性和更好的性能:
^\[([^]]*)\] \[([^]]*)\] \[([^]]*)\] (/[^?]*)(\?.*)?$
使用否定字符类,您不需要使用任何延迟量词,因为[^?]*
将匹配任何不是?
的字符中的0个或更多
答案 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