2

给定一个字符串

Prefix without commas, remainder with optional suffix (optional suffix)

一次匹配和提取字符串的 3 部分的最佳 Java 正则表达式是什么?

  1. 直到第一个逗号的前缀
  2. 到左括号的余数
  3. 括号内的后缀

对于上面的示例,3 个组(引号内)将是

  1. “不带逗号的前缀”
  2. “带有可选后缀的余数”
  3. “(可选后缀)”

字符串的所有 3 个部分都是可变长度的。“余数”部分本身可能包含逗号和括号,可选后缀可能以空格开头,也可能不以空格开头,后跟左括号,后跟零个或多个字符,后跟右括号,后跟可选空格,后跟行结束。

尝试类似的东西

([^,]*),(.*)(\s*\(.*\))?

只产生第 1 组和第 2 组,将第 3 组放在第 2 组的末尾。

4

3 回答 3

2
([^,]*),(.*)(\s*\(.*\))?

失败的原因是正则表达式已经成功([^,]*),(.*)并且不需要检查(回溯)其余部分。

为了让它工作,改变它如下(可能有几个选项),要么匹配没有最后一个括号,要么匹配最后一个括号:

^([^,]*),(.*[^\) ]\s*$) | ([^,]*),(.*)(\s*\(.*\))\s*$

结果($1 + $3and$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)  

编辑:更新上面的正则表达式以允许右括号后的空格(这很微妙,您需要将空格添加到负字符类),并锚定正则表达式以加快速度并减少回溯

于 2015-09-24T21:33:31.383 回答
1

您可以使用以下正则表达式:

"^([^,]*),([^()]*)(\\s*\\(.*\\))?$"

正则表达式匹配:

  • ^- 字符串的开头
  • ([^,]*)- (Group 1) 0 个或多个字符,
  • ,- 字面意思,
  • ([^()]*)- (Group 2) 0 个或多个字符,除了(and)
  • (\\s*\\(.*\\))?-(第 3 组)可选组(由于?量词意味着 1 或 0 次出现前面的子模式):
    • \\s* - 0 个或多个空格
    • \\(.*\\)-literal(然后尽可能多的字符而不是换行符,直到最后一个)
  • $- 字符串结尾(如果实际字符串可能更长,则删除,并且您正在寻找更小的子字符串)。

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) : ""));
于 2015-09-24T21:35:35.133 回答
1

以下正则表达式:

^([^,]*),(.*?)(?:\(([^()]*)\))?\s*$

在组 2 中使用惰性量词来保证组 3 将匹配,如果有任何括号。另一方面,第 3 组不允许嵌套括号,仅在字符串中的最后一组括号中强制匹配。

代码:

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

演示

于 2015-09-24T22:13:53.947 回答