给定一个字符串
Prefix without commas, remainder with optional suffix (optional suffix)
在一次过程中匹配和提取字符串的3个部分的最佳Java正则表达式是什么?
对于上面的示例,3个组(在引号内)将是
字符串的所有3个部分都是可变长度的。余数部分本身可以包含逗号和括号,可选后缀可以以空格开始,也可以不以空格开始,然后是左括号,后面是零个或多个字符,后面是右括号,后面是可选空格,后面是行尾。
试着像
([^,]*),(.*)(\s*\(.*\))?
只产生第1组和第2组,将第3组置于第2组的末尾。
([^,]*),(.*)(\s*\(.*\))?
失败的原因是正则表达式已经成功地执行了([^,]*),(.*)
,并且不需要检查(回溯)其余部分。
要使其正常工作,请按以下方式更改它(可能有几个选项),这些选项要么不匹配最后一个括号,要么将匹配最后一个括号:
^([^,]*),(.*[^\) ]\s*$) | ([^,]*),(.*)(\s*\(.*\))\s*$
结果($1$3
和$2$4
应合并,$1
和$2
,如果没有可选前缀):
3: Prefix without commas
4: remainder with optional suffix
5: (optional suffix)
这里我假设您的可选后缀可以出现多次。阅读问题的另一种方式是希望中间部分重复,即$3
包含在$2
中。您可以按如下方式执行此操作:
^([^,]*),(.*(?:[^\) ]\s*$ | (\s*\(.*\)\s*$)))
结果:
1: Prefix without commas
2: remainder with optional suffix (optional suffix)
3: (optional suffix)
编辑:在正则表达式上面更新,以允许在结束括号后的空白(这很微妙,您需要将空间添加到负字符类),并锚定正则表达式以加速和减少回溯
以下正则表达式:
^([^,]*),(.*?)(?:\(([^()]*)\))?\s*$
在组2中使用惰性量词,以确保如果有括号,则组3将匹配。另一方面,组3不允许嵌套的paren,以强制仅在字符串的最后一组paren中进行匹配。
代码:
String text = "String prefix without commas, variable length ())(remainde()r with )optional (suffix (optional suffix)";
Pattern regex = Pattern.compile("^([^,]*),(.*?)(?:[(]([^()]*)[)])?\\s*$");
Matcher m = regex.matcher(text);
if (m.find()) {
System.out.println("1: " + m.group(1));
System.out.println("2: " + m.group(2));
System.out.println("3: " + m.group(3));
}
输出:
1: String prefix without commas
2: variable length ())(remainde()r with )optional (suffix
3: optional suffix
演示
您可以使用以下正则表达式:
"^([^,]*),([^()]*)(\\s*\\(.*\\))?$"
正则表达式匹配:
^
-字符串的开头([^,]*)
-(第1组)0个或更多字符,而不是,
,
-文字,
,([^()]*)
-(第2组)0个或更多字符,而不是(
和)
(\\s*\\(.\\)代码>-(组3)可选组(由于?
量词表示前面子模式出现1次或0次): \\s*
-0或更多空白 \\(.\\)
-文字(
然后尽可能多的字符,而不是换行符,直到最后一个)
李>
查看IDEONE演示
String str = "String prefix without commas, variable length remainder with optional suffix (optional suffix)";
Pattern ptrn = Pattern.compile("^([^,]*),([^()]*)(\\s*\\(.*\\))?$");
Matcher matcher = ptrn.matcher(str);
while (matcher.find()) {
System.out.println("First group: " + matcher.group(1)
+ "\nSecond group: " + matcher.group(1)
+ (matcher.group(3) != null ?
"\nThrid group: " + matcher.group(3) : ""));