Java 正则表达式匹配除可选后缀外的贪婪数据
Java regex matching greedy data apart from optional suffix
给定一个字符串,如
Prefix without commas, remainder with optional suffix (optional suffix)
什么是最好的 Java 正则表达式来一次性匹配和提取字符串的 3 个部分?
- 前缀到第一个逗号
- 左括号的余数
- 括号内的后缀
对于上面的例子,3 组(引号内)将是
- "Prefix without commas"
- "remainder with optional suffix"
- "(可选后缀)"
字符串的所有 3 个部分都是可变长度的。 "remainder" 部分本身可能包含逗号和圆括号,可选后缀可能以或不以 space(s) 开头,后跟左括号,后跟零个或多个字符,后跟右括号,再后跟通过可选的 spaces,然后是行尾。
尝试类似
([^,]*),(.*)(\s*\(.*\))?
只生成第 1 组和第 2 组,将第 3 组放在第 2 组的末尾。
([^,]*),(.*)(\s*\(.*\))?
失败的原因是正则表达式已经成功 ([^,]*),(.*)
并且不需要检查(回溯)其余部分。
要使其正常工作,请按如下方式更改(可能有多个选项),匹配时不带最后一个括号,或者匹配最后一个括号:
^([^,]*),(.*[^\) ]\s*$) | ([^,]*),(.*)(\s*\(.*\))\s*$
结果( +
和 +
应该合并,</code>和<code>
如果没有可选前缀则填充):
3: Prefix without commas
4: remainder with optional suffix
5: (optional suffix)
这里我假设你的可选后缀可以出现多次。阅读问题的另一种方式是您希望重复中间部分,即 </code> 包含在 <code>
中。您可以按如下方式进行:
^([^,]*),(.*(?:[^\) ]\s*$ | (\s*\(.*\)\s*$)))
结果:
1: Prefix without commas
2: remainder with optional suffix (optional suffix)
3: (optional suffix)
编辑:更新上面的正则表达式以允许在右括号后使用白色space(这很微妙,您需要将 space 添加到否定字符 class),并且锚定正则表达式以加快速度并减少回溯
您可以使用以下正则表达式:
"^([^,]*),([^()]*)(\s*\(.*\))?$"
正则表达式匹配:
^
- 字符串的开头
([^,]*)
-(第 1 组)除 ,
之外的 0 个或更多字符
,
- 文字 ,
([^()]*)
-(第 2 组)除 (
和 )
之外的 0 个或更多字符
(\s*\(.*\))?
-(第 3 组)可选组(由于 ?
量词表示前面的子模式出现 1 次或 0 次):
\s*
- 0 个或更多空格
\(.*\)
- 文字 (
然后尽可能多的字符,而不是换行符,直到最后一个 )
.
$
- 字符串结尾(如果实际字符串可以更长,并且您正在寻找更小的子字符串,则删除)。
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) : ""));
以下正则表达式:
^([^,]*),(.*?)(?:\(([^()]*)\))?\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
给定一个字符串,如
Prefix without commas, remainder with optional suffix (optional suffix)
什么是最好的 Java 正则表达式来一次性匹配和提取字符串的 3 个部分?
- 前缀到第一个逗号
- 左括号的余数
- 括号内的后缀
对于上面的例子,3 组(引号内)将是
- "Prefix without commas"
- "remainder with optional suffix"
- "(可选后缀)"
字符串的所有 3 个部分都是可变长度的。 "remainder" 部分本身可能包含逗号和圆括号,可选后缀可能以或不以 space(s) 开头,后跟左括号,后跟零个或多个字符,后跟右括号,再后跟通过可选的 spaces,然后是行尾。
尝试类似
([^,]*),(.*)(\s*\(.*\))?
只生成第 1 组和第 2 组,将第 3 组放在第 2 组的末尾。
([^,]*),(.*)(\s*\(.*\))?
失败的原因是正则表达式已经成功 ([^,]*),(.*)
并且不需要检查(回溯)其余部分。
要使其正常工作,请按如下方式更改(可能有多个选项),匹配时不带最后一个括号,或者匹配最后一个括号:
^([^,]*),(.*[^\) ]\s*$) | ([^,]*),(.*)(\s*\(.*\))\s*$
结果( +
和 +
应该合并,</code>和<code>
如果没有可选前缀则填充):
3: Prefix without commas
4: remainder with optional suffix
5: (optional suffix)
这里我假设你的可选后缀可以出现多次。阅读问题的另一种方式是您希望重复中间部分,即 </code> 包含在 <code>
中。您可以按如下方式进行:
^([^,]*),(.*(?:[^\) ]\s*$ | (\s*\(.*\)\s*$)))
结果:
1: Prefix without commas
2: remainder with optional suffix (optional suffix)
3: (optional suffix)
编辑:更新上面的正则表达式以允许在右括号后使用白色space(这很微妙,您需要将 space 添加到否定字符 class),并且锚定正则表达式以加快速度并减少回溯
您可以使用以下正则表达式:
"^([^,]*),([^()]*)(\s*\(.*\))?$"
正则表达式匹配:
^
- 字符串的开头([^,]*)
-(第 1 组)除,
之外的 0 个或更多字符
,
- 文字,
([^()]*)
-(第 2 组)除(
和)
之外的 0 个或更多字符
(\s*\(.*\))?
-(第 3 组)可选组(由于?
量词表示前面的子模式出现 1 次或 0 次):\s*
- 0 个或更多空格\(.*\)
- 文字(
然后尽可能多的字符,而不是换行符,直到最后一个)
.
$
- 字符串结尾(如果实际字符串可以更长,并且您正在寻找更小的子字符串,则删除)。
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) : ""));
以下正则表达式:
^([^,]*),(.*?)(?:\(([^()]*)\))?\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