除了可选后缀之外,Java正则表达式匹配贪婪数据

时间:2015-09-24 21:27:58

标签: java regex prefix suffix

给出类似

的字符串
Prefix without commas, remainder with optional suffix (optional suffix)

匹配并在一次传递中提取3个字符串的最佳Java正则表达式是什么?

  1. 第一个逗号的前缀
  2. 左括号内的其余部分
  3. 括号内的后缀
  4. 对于上面的例子,3组(在引号内)将是

    1. “没有逗号的前缀”
    2. “带有可选后缀的余数”
    3. “(可选后缀)”
    4. 弦的所有3个部分都是可变长度的。 “余数”部分可能包含逗号和括号本身,可选后缀可能或不以空格开头,后跟左括号,后跟零个或多个字符,后跟右括号,后跟可选空格,后跟最终的线。

      尝试类似

      的内容
      ([^,]*),(.*)(\s*\(.*\))?
      

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

3 个答案:

答案 0 :(得分: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)  
编辑:更新上面的正则表达式以允许在右括号后面的空格(这是微妙的,你需要将空格添加到负字符类),并锚定正则表达式以加速和减少回溯

答案 1 :(得分:1)

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

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

正则表达式匹配:

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

请参阅IDEONE demo

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) : ""));

答案 2 :(得分:1)

以下正则表达式:

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

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

<强>代码:

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

DEMO