Java 括号外的正则表达式匹配
Java regex match outside bracks
假设有一个字符串:"first option<option 1/option 2/option 3>second option<option 5/option 6/option 7>selection{aaaaa/bbbbb/ccccc}{eeeeee/fffff/ggggg}other string"
现在我想得到3个ArrayList
一个用于“<>”内的字符串:
{"option 1/option 2/option 3", "option 5/option 6/option 7"}
一个用于“{}”中的字符串:
{"aaaaa/bbbbb/ccccc", "eeeeee/fffff/ggggg"}
一个用于 <>/{} 外部和 <>/{} 内部:
{"first option", "<option 1/option 2/option 3>", "second option", "<option 5/option 6/option 7>", "selection", "{aaaaa/bbbbb/ccccc}", "other string"}.
我知道我可以使用如下代码在大括号内获取字符串:
String Str = "first option<option 1/option 2/option 3>second option<option 5/option 6/option 7>selection{aaaaa/bbbbb/ccccc}{eeeeee/fffff/ggggg}other string"`;
Pattern patt = Pattern.compile("<(.*?)>");
Matcher mtchr_r = patt.matcher(Str);
while (mtchr_r.find()){
String ssssssss = mtchr_r.group ();
}
但是如何匹配大括号外的字符串呢?还有,如何按顺序得到第三个ArrayList?
(?<=<)[^>]*(?=>)|(?<={)[^}]*(?=})
您可以使用它来获取 <>
和 {}
中的两个字符串。参见演示。
https://regex101.com/r/pM9yO9/19
使用它来单独获取所有内容,包括外面的内容。
(?<=<)[^>]*(?=>)|(?<={)[^}]*(?=})|[^<>{}]+
一个选择是使用匹配所有情况的正则表达式,例如(<[^>]*>)|(\{[^}]*\})|([^{<]*)
(在 Java 中你必须转义 \
s)
然而,这不允许您区分找到的匹配类型(<...>
、{...}
或其余文本)。因此,按照您的问题的评论中的建议,使用 3 个正则表达式可能会更好:
Pattern pattern1 = Pattern.compile("<(.*?)>");
Pattern pattern2 = Pattern.compile("\{(.*?)\}");
Pattern pattern3 = Pattern.compile("(<[^>]*>)|(\{[^}]*\})|([^{<]*)");
然后您可以简单地将所有匹配项添加到您的列表中。
我认为对于第三个,只有一个正则表达式是不正确的。我建议为您的三个阵列制作三种不同的图案。:
String Str = "first option<option 1/option 2/option 3>second option<option 5/option 6/option 7>selection{aaaaa/bbbbb/ccccc}{eeeeee/fffff/ggggg}other string";
Pattern inside = Pattern.compile("<(.*?)>");
Pattern insideBrackets = Pattern.compile("\{(.+?)\}");
Pattern inAndOutside = Pattern.compile("(<[^>]*>)|(\{[^}]*\})|([^{<]*)");
Matcher matcher1 = inside.matcher(Str);
Matcher matcher2 = insideBrackets.matcher(Str);
Matcher matcher3 = inAndOutside.matcher(Str);
ArrayList<String> array1 = new ArrayList<>();
ArrayList<String> array2 = new ArrayList<>();
ArrayList<String> array3 = new ArrayList<>();
boolean found = false;
while (matcher1.find()) {
array1.add(matcher1.group(1));
System.out.println(matcher1.group(1));
found = true;
}
while (matcher2.find()) {
array2.add(matcher2.group(1));
System.out.println(matcher2.group(1));
found = true;
}
while (matcher3.find()) {
array3.add(matcher3.group(1));
System.out.println(matcher3.group(1));
found = true;
}
if (!found) {
System.out.println("No match found");
}
}
使用\G
(断言下一场比赛从上一场比赛结束的地方开始),可以一次完成:
\G(?:[^<>{}]++|<(?<pointy>[^<>]++)>|\{(?<curly>[^{}]++)\})
上面正则表达式的简单分解:
\G # Must start from where last match ends
(?:
[^<>{}]++ # Outside {} <>
| # OR
<(?<pointy>[^<>]++)> # Capture content inside < > in group named 'pointy'
| # OR
\{(?<curly>[^{}]++)\} # Capture content inside < > in group named 'curly'
)
假设<>
里面没有<>
,{}
里面没有{}
,也没有不匹配的<>{}
,上面的正则表达式应该正确分割字符串。
正则表达式将在遇到无效序列的第一个位置停止,因此在我下面的示例代码中,我确保最后一个匹配的位置在字符串的末尾。
完整示例程序(Java 7,但您可以删除命名的捕获组,使其成为 Java 以前版本中的 运行:
import java.util.ArrayList;
import java.util.regex.Matcher;
import java.util.regex.Pattern;
public class SO28210525 {
private static final Pattern re = Pattern.compile("\G(?:[^<>{}]++|<(?<pointy>[^<>]++)>|\{(?<curly>[^{}]++)\})");
public static void main(String[] args) {
String input = "first option<option 1/option 2/option 3>second option<option 5/option 6/option 7>selection{aaaaa/bbbbb/ccccc}{eeeeee/fffff/ggggg}other string";
Matcher matcher = re.matcher(input);
ArrayList<String> tokens = new ArrayList<String>();
ArrayList<String> curly = new ArrayList<String>();
ArrayList<String> pointy = new ArrayList<String>();
int lastIndex = 0;
while (matcher.find()) {
tokens.add(matcher.group(0));
String inCurly = matcher.group("curly");
if (inCurly != null) {
curly.add(inCurly);
}
String inPointy = matcher.group("pointy");
if (inPointy != null) {
pointy.add(inPointy);
}
lastIndex = matcher.end(0);
}
if (lastIndex != input.length()) {
System.err.println("Invalid input");
} else {
System.out.println(tokens);
System.out.println(curly);
System.out.println(pointy);
}
}
}
在以前的Java版本(6及以下)中,作为替代,您可以使用Matcher.start
或Matcher.end
方法来检查捕获组是否捕获了某些东西。
但是,在Java 7 中,缺少命名捕获组的相应Matcher.start
和Matcher.end
方法(只有Matcher.group
可用)。这2个方法后来在Java 8.
中添加
假设有一个字符串:"first option<option 1/option 2/option 3>second option<option 5/option 6/option 7>selection{aaaaa/bbbbb/ccccc}{eeeeee/fffff/ggggg}other string"
现在我想得到3个ArrayList
一个用于“<>”内的字符串:
{"option 1/option 2/option 3", "option 5/option 6/option 7"}
一个用于“{}”中的字符串:
{"aaaaa/bbbbb/ccccc", "eeeeee/fffff/ggggg"}
一个用于 <>/{} 外部和 <>/{} 内部:
{"first option", "<option 1/option 2/option 3>", "second option", "<option 5/option 6/option 7>", "selection", "{aaaaa/bbbbb/ccccc}", "other string"}.
我知道我可以使用如下代码在大括号内获取字符串:
String Str = "first option<option 1/option 2/option 3>second option<option 5/option 6/option 7>selection{aaaaa/bbbbb/ccccc}{eeeeee/fffff/ggggg}other string"`;
Pattern patt = Pattern.compile("<(.*?)>");
Matcher mtchr_r = patt.matcher(Str);
while (mtchr_r.find()){
String ssssssss = mtchr_r.group ();
}
但是如何匹配大括号外的字符串呢?还有,如何按顺序得到第三个ArrayList?
(?<=<)[^>]*(?=>)|(?<={)[^}]*(?=})
您可以使用它来获取 <>
和 {}
中的两个字符串。参见演示。
https://regex101.com/r/pM9yO9/19
使用它来单独获取所有内容,包括外面的内容。
(?<=<)[^>]*(?=>)|(?<={)[^}]*(?=})|[^<>{}]+
一个选择是使用匹配所有情况的正则表达式,例如(<[^>]*>)|(\{[^}]*\})|([^{<]*)
(在 Java 中你必须转义 \
s)
然而,这不允许您区分找到的匹配类型(<...>
、{...}
或其余文本)。因此,按照您的问题的评论中的建议,使用 3 个正则表达式可能会更好:
Pattern pattern1 = Pattern.compile("<(.*?)>");
Pattern pattern2 = Pattern.compile("\{(.*?)\}");
Pattern pattern3 = Pattern.compile("(<[^>]*>)|(\{[^}]*\})|([^{<]*)");
然后您可以简单地将所有匹配项添加到您的列表中。
我认为对于第三个,只有一个正则表达式是不正确的。我建议为您的三个阵列制作三种不同的图案。:
String Str = "first option<option 1/option 2/option 3>second option<option 5/option 6/option 7>selection{aaaaa/bbbbb/ccccc}{eeeeee/fffff/ggggg}other string";
Pattern inside = Pattern.compile("<(.*?)>");
Pattern insideBrackets = Pattern.compile("\{(.+?)\}");
Pattern inAndOutside = Pattern.compile("(<[^>]*>)|(\{[^}]*\})|([^{<]*)");
Matcher matcher1 = inside.matcher(Str);
Matcher matcher2 = insideBrackets.matcher(Str);
Matcher matcher3 = inAndOutside.matcher(Str);
ArrayList<String> array1 = new ArrayList<>();
ArrayList<String> array2 = new ArrayList<>();
ArrayList<String> array3 = new ArrayList<>();
boolean found = false;
while (matcher1.find()) {
array1.add(matcher1.group(1));
System.out.println(matcher1.group(1));
found = true;
}
while (matcher2.find()) {
array2.add(matcher2.group(1));
System.out.println(matcher2.group(1));
found = true;
}
while (matcher3.find()) {
array3.add(matcher3.group(1));
System.out.println(matcher3.group(1));
found = true;
}
if (!found) {
System.out.println("No match found");
}
}
使用\G
(断言下一场比赛从上一场比赛结束的地方开始),可以一次完成:
\G(?:[^<>{}]++|<(?<pointy>[^<>]++)>|\{(?<curly>[^{}]++)\})
上面正则表达式的简单分解:
\G # Must start from where last match ends
(?:
[^<>{}]++ # Outside {} <>
| # OR
<(?<pointy>[^<>]++)> # Capture content inside < > in group named 'pointy'
| # OR
\{(?<curly>[^{}]++)\} # Capture content inside < > in group named 'curly'
)
假设<>
里面没有<>
,{}
里面没有{}
,也没有不匹配的<>{}
,上面的正则表达式应该正确分割字符串。
正则表达式将在遇到无效序列的第一个位置停止,因此在我下面的示例代码中,我确保最后一个匹配的位置在字符串的末尾。
完整示例程序(Java 7,但您可以删除命名的捕获组,使其成为 Java 以前版本中的 运行:
import java.util.ArrayList;
import java.util.regex.Matcher;
import java.util.regex.Pattern;
public class SO28210525 {
private static final Pattern re = Pattern.compile("\G(?:[^<>{}]++|<(?<pointy>[^<>]++)>|\{(?<curly>[^{}]++)\})");
public static void main(String[] args) {
String input = "first option<option 1/option 2/option 3>second option<option 5/option 6/option 7>selection{aaaaa/bbbbb/ccccc}{eeeeee/fffff/ggggg}other string";
Matcher matcher = re.matcher(input);
ArrayList<String> tokens = new ArrayList<String>();
ArrayList<String> curly = new ArrayList<String>();
ArrayList<String> pointy = new ArrayList<String>();
int lastIndex = 0;
while (matcher.find()) {
tokens.add(matcher.group(0));
String inCurly = matcher.group("curly");
if (inCurly != null) {
curly.add(inCurly);
}
String inPointy = matcher.group("pointy");
if (inPointy != null) {
pointy.add(inPointy);
}
lastIndex = matcher.end(0);
}
if (lastIndex != input.length()) {
System.err.println("Invalid input");
} else {
System.out.println(tokens);
System.out.println(curly);
System.out.println(pointy);
}
}
}
在以前的Java版本(6及以下)中,作为替代,您可以使用Matcher.start
或Matcher.end
方法来检查捕获组是否捕获了某些东西。
但是,在Java 7 中,缺少命名捕获组的相应Matcher.start
和Matcher.end
方法(只有Matcher.group
可用)。这2个方法后来在Java 8.