在Java中查找正则表达式模式的所有匹配项 - 包括重叠的匹配项

3

我有一个形如:

1,2,3,4,5,6,7,8,...

的字符串。我想要找出所有恰好包含4个数字的子字符串,为此我使用正则表达式[0-9],[0-9],[0-9],[0-9]。但不幸的是,当我尝试将正则表达式与我的字符串匹配时,我无法获得所有可能的子字符串,只有一部分。比如在上面的示例中,我只会得到:

1,2,3,4

5,6,7,8

虽然我期望得到:

1,2,3,4

2,3,4,5

3,4,5,6

...

我该如何找到与我的正则表达式相对应的所有匹配项呢?


另外,我正在使用PatternMatcher来查找匹配项:

Pattern pattern = Pattern.compile([0-9],[0-9],[0-9],[0-9]);
Matcher matcher = pattern.matcher(myString);
    
List<String> matches = new ArrayList<String>();
    
while (matcher.find())
{
  matches.add(matcher.group());
}

我认为正则表达式不是完成该任务的好方法。在这里使用“substring”可能更好。 - XtremeBaumer
@XtremeBaumer 你能详细说明一下吗? - user2233125
请查看我的答案以获取更多信息。 - XtremeBaumer
4个回答

4

默认情况下,连续调用Matcher.find()会从上一个匹配的结尾开始。

如果要从特定位置开始查找,请将起始位置参数传递给find函数,并使其超过前一个find的起始位置。

在您的情况下,可能需要这样做:

while (matcher.find(matcher.start()+1))

这个可以正常工作:

Pattern p = Pattern.compile("[0-9],[0-9],[0-9],[0-9]");

public void test(String[] args) throws Exception {
    String test = "0,1,2,3,4,5,6,7,8,9";
    Matcher m = p.matcher(test);
    if(m.find()) {
        do {
            System.out.println(m.group());
        } while(m.find(m.start()+1));
    }
}

打印

0,1,2,3

1,2,3,4

...


(\d,){3}\d 可能更加简洁 :-) - Aniket Sahrawat
@AniketSahrawat 你是指 \\d,对吗? - Alex Savitsky
显然,我们总是要转义 \\ ;) - Aniket Sahrawat

2

如果您正在寻找纯基于正则表达式的解决方案,那么您可以使用此基于前瞻的正则表达式来获取重叠匹配:

(?=((?:[0-9],){3}[0-9]))

请注意,您的匹配项可在捕获组#1中使用。
代码:
```

RegEx Demo

```
    final String regex = "(?=((?:[0-9],){3}[0-9]))";
    final String string = "0,1,2,3,4,5,6,7,8,9";

    final Pattern pattern = Pattern.compile(regex);
    final Matcher matcher = pattern.matcher(string);

    while (matcher.find()) {
        System.out.println(matcher.group(1));
    }

代码演示

输出:

0,1,2,3
1,2,3,4
2,3,4,5
3,4,5,6
4,5,6,7
5,6,7,8
6,7,8,9

1

以下是一些没有使用正则表达式的示例代码(因为对我来说似乎没什么用)。此外,我认为在这种情况下使用正则表达式会更慢。但只要数字只有1个字符长,它就能按原样工作。

String s = "a,b,c,d,e,f,g,h";
for (int i = 0; i < s.length() - 8; i+=2) {
    System.out.println(s.substring(i, i + 7));
}

这个字符串的输出是:
a,b,c,d
b,c,d,e
c,d,e,f
d,e,f,g

1
正如@OldCurmudgeon指出的那样,默认情况下find()从上一个匹配项的末尾开始查找。为了将其定位在第一个匹配元素之后,请将第一个匹配区域引入为捕获组,并使用其结束索引:
Pattern pattern = Pattern.compile("(\\d,)\\d,\\d,\\d");
Matcher matcher = pattern.matcher("1,2,3,4,5,6,7,8,9");
List<String> matches = new ArrayList<>();
int start = 0;
while (matcher.find(start)) {
    start = matcher.end(1);
    matches.add(matcher.group());
}
System.out.println(matches);

结果在。
[1,2,3,4, 2,3,4,5, 3,4,5,6, 4,5,6,7, 5,6,7,8, 6,7,8,9]

这种方法也适用于匹配区域超过一个数字的情况。

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接