Java正则表达式匹配贪婪数据(可选后缀除外)

Java正则表达式匹配贪婪数据(可选后缀除外),java,regex,prefix,suffix,Java,Regex,Prefix,Suffix,给定一个字符串 Prefix without commas, remainder with optional suffix (optional suffix) 在一次过程中匹配和提取字符串的3个部分的最佳Java正则表达式是什么 直到第一个逗号的前缀 剩余部分一直到左括号 括号内的后缀 对于上面的示例,引号中的3个组是 不带逗号的前缀 带可选后缀的余数 可选后缀 字符串的所有3个部分都具有可变长度。其余部分可能包含逗号和括号本身,可选后缀可能以空格开头,也可能不以空格开头,后跟左括号,后跟零个

给定一个字符串

Prefix without commas, remainder with optional suffix (optional suffix)
在一次过程中匹配和提取字符串的3个部分的最佳Java正则表达式是什么

直到第一个逗号的前缀 剩余部分一直到左括号 括号内的后缀 对于上面的示例,引号中的3个组是

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

试着像

([^,]*),(.*)(\s*\(.*\))?
只产生第1组和第2组,将第3组置于第2组的末尾

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

要使其正常工作,请按以下几种可能的选项进行更改,这些选项要么不带最后一个括号匹配,要么将与最后一个括号匹配:

^([^,]*),(.*[^\) ]\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*\\(.*\\))?$"
^([^,]*),(.*?)(?:\(([^()]*)\))?\s*$
正则表达式匹配:

^-字符串的开头 [^,]*-第1组包含0个或更多字符,而不是, ,-文字, [^]*-第2组0个或更多字符,而不是和 \\s*\\.\\\?-第3组可选组由于什么原因?表示前面子模式出现1次或0次的量词: \\s*-0或更多空格 \\.\\\文字,然后尽可能多的字符,而不是换行符,直到最后一个字符。 $-如果实际字符串可能更长,并且您正在寻找更小的子字符串,则删除字符串结尾。 看

以下正则表达式:

"^([^,]*),([^()]*)(\\s*\\(.*\\))?$"
^([^,]*),(.*?)(?:\(([^()]*)\))?\s*$
在组2中使用惰性量词,以确保如果有括号,则组3将匹配。另一方面,组3不允许嵌套的paren,以强制仅在字符串的最后一组paren中进行匹配

代码:

输出:


逗号后的.*将把逗号后的所有内容合并到第2组..*?虽然我还没试过,但可能行得通。如果剩下的部分有左括号,就行不通了。实际上,我们正在搜索最后一个左括号(如果有的话)。不起作用,它将第3组放在第2组的末尾,并为第3组提供null。哦,对不起,没有找到。不用担心。另外,你组成第二组的前提是这里没有括号,这不一定是事实。我会试试,谢谢。是否有一个单一的解决方案?@PNS,您的问题的性质至少需要一些回溯,但这一个,特别是第二个,将回溯最小化到可选部分的大小。或者,您可以使用非贪婪说明符,但它们通常比贪婪说明符慢。也可以使用负前瞻,但同样,这通常较慢。最后一个正则表达式有一个未关闭的组。谢谢您的帮助。@PNS:我更新了它,使它稍微更有效,并修复了一个突出的括号错误。@PNS:是的,上一个正则表达式错过了一个结束符,这是同时修复的,您需要刷新;。我用测试了它,这与Java正则表达式不同,但是对于这个特殊的正则表达式没有区别,如果你有Silverlight,我喜欢它的接口。至于正则表达式失败的原因,第二个。*确实消耗了从开始到结束的一切,不需要放弃任何符号到可选组。我试图将捕获组号保持在最小值,并注意到,由于组3是可选的,我们需要在稍后的代码中访问它时检查它是否为null。如果我可以访问源代码,这将起作用。该用例用于提供一个正则表达式,该正则表达式在matches返回true后工作。这将与matches一起工作,只需删除^和$,这将是多余的。顺便说一句,这是你的答案。
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