如何获取给定正则表达式的所有子字符串?

2022-09-02 03:57:57

我需要让所有子字符串都与正则表达式匹配,我知道我可以为它构建一个自动机,但我正在寻找一个更简单的解决方案。
问题是,Matcher.find()不会返回所有结果。

String str = "abaca";
Matcher matcher = Pattern.compile("a.a").matcher(str);
while (matcher.find()) {
   System.out.println(str.substring(matcher.start(),matcher.end()));
}

结果是,而不是我想要的...
任何想法?
编辑:另一个例子:对于string=abaa,regex=a.*a我期望得到aba,abaa,aa
p.s.如果不能使用正则表达式实现,它也是一个答案,我只是想知道我不是在为语言已经为我提供的东西重新发明轮子......abaaba,aca


答案 1

你可以做这样的事情:

import java.util.*;
import java.util.regex.Matcher;
import java.util.regex.Pattern;

public class Main {

    public static List<String> getAllMatches(String text, String regex) {
        List<String> matches = new ArrayList<String>();
        Matcher m = Pattern.compile("(?=(" + regex + "))").matcher(text);
        while(m.find()) {
            matches.add(m.group(1));
        }
        return matches;
    }

    public static void main(String[] args) {
        System.out.println(getAllMatches("abaca", "a.a"));
        System.out.println(getAllMatches("abaa", "a.*a"));
    }
}

哪些打印:

[aba, aca]
[abaa, aa]

唯一的问题是你从最后的比赛列表中消失了。这是因为 贪婪 在 .您无法使用正则表达式解决此问题。您可以通过迭代所有可能的子字符串并调用每个子字符串来执行此操作:aba.*a.*a.matches(regex)

public static List<String> getAllMatches(String text, String regex) {
    List<String> matches = new ArrayList<String>();
    for(int length = 1; length <= text.length(); length++) {
        for(int index = 0; index <= text.length()-length; index++) {
            String sub = text.substring(index, index + length);
            if(sub.matches(regex)) {
                matches.add(sub);
            }
        }
    }
    return matches;
}

如果文本保持相对较小,这将起作用,但对于较大的字符串,这可能会变得计算量过大。


答案 2

默认情况下,新匹配项从前一个匹配项的末尾开始。如果匹配项可以重叠,则需要手动指定起始点:

int start = 0;
while (matcher.find(start)) { 
    ...
    start = matcher.start() + 1;
}