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

时间:2011-04-18 15:20:06

标签: java regex string

我需要让所有子字符串与正则表达式匹配,我知道我可以为它构建一个自动机,但我正在寻找一个更简单的解决方案。 问题是,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()));
}

我想要的结果是aba而不是aba,aca ... 任何想法?
修改 另一个例子:for string = abaa,regex = a。* a我期待得到aba,abaa,aa
附:如果用正则表达式无法实现,那也是一个答案,我只是想知道我不是在为语言已经为我提供的东西重新发明轮子......

4 个答案:

答案 0 :(得分:17)

你可以这样做:

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;
}

如果你的文字保持相对较小,这将有效,但对于较大的字符串,这可能会变得太计算。

答案 1 :(得分:7)

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

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

答案 2 :(得分:0)

matcher.find(startingFrom)循环中使用while,并将startingFrom增加到比上一个匹配开头多一个:startingFrom = matcher.start()+1;

答案 3 :(得分:0)

这是一种计算上开放式的问题。正则表达式的所有可能匹配的问题可以改为

What are all the possible sub strings of a given String that match the given regex?

那么你的代码真正需要做的是(伪代码):

for(String substring: allPossibleSubstrings) {
    if(PATTERN.matches(subString) {
        results.add(subString);
    }
}

现在对于像abaa这样的字符串,这很简单:AllPossible = ["a", "ab", "aba", "abaa", "ba", "baa", "aa"] 您还可以通过将子字符串的大小限制为正则表达式可以匹配的最小大小来添加一些智能。当然,对于大字符串,这将呈指数级扩展