在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

我有一个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-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()
调用,因为“上一个匹配”