[英]Split a string into several substrings using regex. Both matches and non-matches should be returned
[英]Find multiple regex matches in Java prohibiting non-matches
我有一個 Java Pattern
例如\\s+(foo|bar)
來查找空格后foo
或bar
所有匹配項。 使用匹配組,我可以提取實際匹配的文本。
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.