在Java中查找多个正则表达式匹配项,禁止不匹配项
我有一个Java在Java中查找多个正则表达式匹配项,禁止不匹配项,java,regex,regex-group,Java,Regex,Regex Group,我有一个Java模式,比如\s+(foo | bar)来查找空格后foo或bar的所有匹配项。使用匹配组,我可以提取实际匹配的文本 Pattern=Pattern.compile(“\\s+(foo | bar)”); Matcher Matcher=pattern.match(someText); while(matcher.find()){ 字符串值=matcher.group(1); ... } 这适用于像foo-foo-bar(注意前面的空格)这样的字符串,但它也会匹配像foo-foo
模式
,比如\s+(foo | bar)
来查找空格后foo
或bar
的所有匹配项。使用匹配组,我可以提取实际匹配的文本
Pattern=Pattern.compile(“\\s+(foo | bar)”);
Matcher Matcher=pattern.match(someText);
while(matcher.find()){
字符串值=matcher.group(1);
...
}
这适用于像foo-foo-bar
(注意前面的空格)这样的字符串,但它也会匹配像foo-foo-bad
这样的字符串。我怎样才能阻止匹配器匹配不匹配的后续字符运行,或者检测到已跳过字符或没有更多字符剩余?换句话说,我希望匹配的整个字符串是一系列与模式匹配的后续字符串。我怎么能保证呢
这里的要点是继续通过字符串查找匹配项。我可以很容易地分割字符串,然后执行额外的比较,但我不希望多个regex过程、数组/列表创建等的开销。在regex前面加上
\G
。Javadoc说:
\G
-上一次匹配的结束
当然,在第一个匹配中,“上一个匹配的结束”是输入的开始
这确保正则表达式匹配都是连续的,从输入的开头开始。这并不意味着正则表达式将到达输入的末尾,您必须自己进行检查
范例
输出
“abc”
未完成:最后一场比赛在0结束
“富富酒吧”
g0='foo'(0-4),g1='foo'(1-4)
g0='foo'(4-8),g1='foo'(5-8)
g0=‘巴’(8-12),g1=‘巴’(9-12)
好啊
“foo foo bad”
g0='foo'(0-4),g1='foo'(1-4)
g0='foo'(4-8),g1='foo'(5-8)
未完成:最后一场比赛在8点结束
“foo bad foo”
g0='foo'(0-4),g1='foo'(1-4)
未完成:最后一场比赛在4点结束
为了进行比较,如果正则表达式中没有\G
,则该代码的输出将为:
“abc”
未完成:最后一场比赛在0结束
“富富酒吧”
g0='foo'(0-4),g1='foo'(1-4)
g0='foo'(4-8),g1='foo'(5-8)
g0=‘巴’(8-12),g1=‘巴’(9-12)
好啊
“foo foo bad”
g0='foo'(0-4),g1='foo'(1-4)
g0='foo'(4-8),g1='foo'(5-8)
未完成:最后一场比赛在8点结束
“foo bad foo”
g0='foo'(0-4),g1='foo'(1-4)
g0='foo'(8-12),g1='foo'(9-12)
好啊
如您所见,上一个示例将无法检测到已跳过的文本
bad
。在正则表达式前面加上\G
。Javadoc说:
\G
-上一次匹配的结束
当然,在第一个匹配中,“上一个匹配的结束”是输入的开始
这确保正则表达式匹配都是连续的,从输入的开头开始。这并不意味着正则表达式将到达输入的末尾,您必须自己进行检查
范例
输出
“abc”
未完成:最后一场比赛在0结束
“富富酒吧”
g0='foo'(0-4),g1='foo'(1-4)
g0='foo'(4-8),g1='foo'(5-8)
g0=‘巴’(8-12),g1=‘巴’(9-12)
好啊
“foo foo bad”
g0='foo'(0-4),g1='foo'(1-4)
g0='foo'(4-8),g1='foo'(5-8)
未完成:最后一场比赛在8点结束
“foo bad foo”
g0='foo'(0-4),g1='foo'(1-4)
未完成:最后一场比赛在4点结束
为了进行比较,如果正则表达式中没有\G
,则该代码的输出将为:
“abc”
未完成:最后一场比赛在0结束
“富富酒吧”
g0='foo'(0-4),g1='foo'(1-4)
g0='foo'(4-8),g1='foo'(5-8)
g0=‘巴’(8-12),g1=‘巴’(9-12)
好啊
“foo foo bad”
g0='foo'(0-4),g1='foo'(1-4)
g0='foo'(4-8),g1='foo'(5-8)
未完成:最后一场比赛在8点结束
“foo bad foo”
g0='foo'(0-4),g1='foo'(1-4)
g0='foo'(8-12),g1='foo'(9-12)
好啊
如您所见,上一个示例将无法检测到已跳过的文本
错误。需要进行额外匹配的解决方案是首先尝试将输入与以下正则表达式匹配:
^(\s+(foo|bar))+$
然后您可以重复查找:
import java.util.regex.Pattern;
import java.util.regex.Matcher;
public class Test
{
public static void main(String[] args) {
String[] tests = {
" foo foo bar",
" foo foo x foo bar"
};
Pattern pattern1 = Pattern.compile("(\\s+(foo|bar))+");
Pattern pattern2 = Pattern.compile("\\s+(foo|bar)");
for (int i = 0; i < tests.length; i++) {
String test = tests[i];
Matcher m1 = pattern1.matcher(test);
if (m1.matches()) {
System.out.println("Matches against: '" + test + "'");
Matcher m2 = pattern2.matcher(test);
while (m2.find()) {
System.out.println("\t'" + m2.group() + "'");
}
}
}
}
}
如果整个输入不必匹配,那么我们使用正则表达式查找匹配字符串的前缀:
^(\s+(foo|bar))+
您可以根据输入测试此匹配的长度,以确定整个字符串是否匹配
然后:
import java.util.regex.Pattern;
import java.util.regex.Matcher;
public class Test
{
public static void main(String[] args) {
String[] tests = {
" foo foo bar",
" foo foo x foo bar"
};
Pattern pattern1 = Pattern.compile("^(\\s+(foo|bar))+");
Pattern pattern2 = Pattern.compile("\\s+(foo|bar)");
for (int i = 0; i < tests.length; i++) {
String test = tests[i];
Matcher m1 = pattern1.matcher(test);
if (m1.find()) {
String s = m1.group();
System.out.println("Matches against: '" + s + "'");
Matcher m2 = pattern2.matcher(s);
while (m2.find()) {
System.out.println("\t'" + m2.group() + "'");
}
}
}
}
}
需要进行额外的匹配的解决方案是首先尝试将输入与以下正则表达式匹配:
^(\s+(foo|bar))+$
然后您可以重复查找:
import java.util.regex.Pattern;
import java.util.regex.Matcher;
public class Test
{
public static void main(String[] args) {
String[] tests = {
" foo foo bar",
" foo foo x foo bar"
};
Pattern pattern1 = Pattern.compile("(\\s+(foo|bar))+");
Pattern pattern2 = Pattern.compile("\\s+(foo|bar)");
for (int i = 0; i < tests.length; i++) {
String test = tests[i];
Matcher m1 = pattern1.matcher(test);
if (m1.matches()) {
System.out.println("Matches against: '" + test + "'");
Matcher m2 = pattern2.matcher(test);
while (m2.find()) {
System.out.println("\t'" + m2.group() + "'");
}
}
}
}
}
如果整个输入不必匹配,那么我们使用正则表达式查找匹配字符串的前缀:
^(\s+(foo|bar))+
您可以根据输入测试此匹配的长度,以确定整个字符串是否匹配
然后:
import java.util.regex.Pattern;
import java.util.regex.Matcher;
public class Test
{
public static void main(String[] args) {
String[] tests = {
" foo foo bar",
" foo foo x foo bar"
};
Pattern pattern1 = Pattern.compile("^(\\s+(foo|bar))+");
Pattern pattern2 = Pattern.compile("\\s+(foo|bar)");
for (int i = 0; i < tests.length; i++) {
String test = tests[i];
Matcher m1 = pattern1.matcher(test);
if (m1.find()) {
String s = m1.group();
System.out.println("Matches against: '" + s + "'");
Matcher m2 = pattern2.matcher(s);
while (m2.find()) {
System.out.println("\t'" + m2.group() + "'");
}
}
}
}
}
那么bad foo foo bar
呢?@Nick,我也不想匹配它,我想知道有一些字符不匹配。你能包括一些示例输入以及确切的输出应该是什么吗。这对我来说并不清楚。关于bad foo foo bar
呢?@Nick,我也不想匹配它,我想知道有一些字符不匹配。你能包括一些示例输入以及确切的输出应该是什么吗。我不清楚,安德烈亚斯,这太棒了!这正是我一直在寻找的东西;非常感谢你。有一点需要注意的是:\G
阻止将模式嵌入到更大的正则表达式中(例如“test((?:“+pattern+”)+”)”
),因此如果两者都需要,则需要将模式提取为两个:用于嵌入的普通模式,另一个前缀为\G
用于迭代匹配。@GarretWilson\G
仅在进行多个匹配时使用,即进行多个find()
调用,因为“上一个匹配”