簡體   English   中英

在 Java 中查找多個正則表達式匹配,禁止不匹配

[英]Find multiple regex matches in Java prohibiting non-matches

我有一個 Java Pattern例如\\s+(foo|bar)來查找空格后foobar所有匹配項。 使用匹配組,我可以提取實際匹配的文本。

Pattern pattern=Pattern.compile("\\s+(foo|bar)");
Matcher matcher = pattern.match(someText);
while(matcher.find()) {
  String value = matcher.group(1);
  ...
}

這適用於像foo foo bar這樣的字符串(注意前面的空格),但它也會匹配像foo foo bad類的東西。 我如何才能阻止匹配器匹配不匹配的后續字符運行,或者檢測到字符被跳過或沒有更多字符剩余? 換句話說,我希望匹配的整個字符串是與模式匹配的后續字符串序列。 我怎么能保證這一點?

這里的重點是繼續通過字符串查找匹配項。 我可以輕松地拆分字符串,然后執行額外的比較,但我不想要多個正則表達式傳遞、數組/列表創建等的開銷。

\\G前綴正則表達式。 Pattern Javadoc 說:

\\G - 上一場比賽的結束

當然,在第一場比賽中,“前一場比賽的結束”就是輸入的開始。

這確保了正則表達式匹配都是連續的,從輸入的開頭開始。 並不意味着正則表達式會到達輸入的末尾,您必須自己檢查。

例子

public static void main(String[] args) {
    test("abc");
    test(" foo foo bar");
    test(" foo foo bad");
    test(" foo bad foo");
}
static void test(String input) {
    System.out.println("'" + input + "'");
    int lastEnd = 0;
    Matcher m = Pattern.compile("\\G\\s+(foo|bar)").matcher(input);
    while (m.find()) {
        System.out.printf("  g0='%s' (%d-%d), g1='%s' (%d-%d)%n",
                          m.group(), m.start(), m.end(),
                          m.group(1), m.start(1), m.end(1));
        lastEnd = m.end();
    }
    if (lastEnd == input.length())
        System.out.println("  OK");
    else
        System.out.println("  Incomplete: Last match ended at " + lastEnd);
}

輸出

'abc'
  Incomplete: Last match ended at 0
' foo foo bar'
  g0=' foo' (0-4), g1='foo' (1-4)
  g0=' foo' (4-8), g1='foo' (5-8)
  g0=' bar' (8-12), g1='bar' (9-12)
  OK
' foo foo bad'
  g0=' foo' (0-4), g1='foo' (1-4)
  g0=' foo' (4-8), g1='foo' (5-8)
  Incomplete: Last match ended at 8
' foo bad foo'
  g0=' foo' (0-4), g1='foo' (1-4)
  Incomplete: Last match ended at 4

為了比較,如果正則表達式中沒有\\G ,該代碼的輸出將是:

'abc'
  Incomplete: Last match ended at 0
' foo foo bar'
  g0=' foo' (0-4), g1='foo' (1-4)
  g0=' foo' (4-8), g1='foo' (5-8)
  g0=' bar' (8-12), g1='bar' (9-12)
  OK
' foo foo bad'
  g0=' foo' (0-4), g1='foo' (1-4)
  g0=' foo' (4-8), g1='foo' (5-8)
  Incomplete: Last match ended at 8
' foo bad foo'
  g0=' foo' (0-4), g1='foo' (1-4)
  g0=' foo' (8-12), g1='foo' (9-12)
  OK

如您所見,最后一個示例將無法檢測到該文本bad wa 被跳過。

需要進行額外match解決方案是首先嘗試將輸入與以下正則表達式匹配:

^(\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() + "'");
                }
            }
        }
    }
}

印刷:

Matches against: ' foo foo bar'
        ' foo'
        ' foo'
        ' bar'

如果整個輸入不必匹配,那么我們使用正則表達式來查找匹配的字符串的前綴:

^(\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() + "'");
                }
            }
        }
    }
}

印刷:

Matches against: ' foo foo bar'
        ' foo'
        ' foo'
        ' bar'
Matches against: ' foo foo'
        ' foo'
        ' foo'

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM