如何检查字符串是否可以被正则表达式匹配耗尽?

时间:2013-01-01 16:59:36

标签: java regex

所以问题是确定字符串中的每个字符是否都包含在特定正则表达式的匹配中。或者,以不同的方式说明,如果可以包含在特定正则表达式的某些匹配中的所有字符位置的集合包括字符串中的所有字符位置。

我的想法是做这样的事情:

boolean matchesAll(String myString, Matcher myMatcher){
    boolean matched[] = new boolean[myString.size()];
    for(myMatcher.reset(myString); myMatcher.find();)
        for(int idx = myMatcher.start(); idx < myMatcher.end(); idx++)
            matched[idx] = true;

    boolean allMatched = true;
    for(boolean charMatched : matched)
        allMatched &= charMatched;

    return allMatched
}

有没有更好的方法呢?

另外,在我写这篇文章的时候,我发现在

这样的情况下我不会做我想做的事情。
matchesAll("abcabcabc", Pattern.compile("(abc){2}").matcher()); //returns false

因为Matcher仅在最后一场比赛结束时尝试匹配。我希望它返回true,因为如果你在第3位开始匹配,它可以在匹配中包含第三个abc

boolean matchesAll(String myString, Matcher myMatcher){

    boolean matched[] = new boolean[myString.size()];
    boolean allMatched = true;

    for(int idx = 0; idx < myString.size() && myMatcher.find(idx);
            idx = myMatcher.start() + 1) {

        for(int idx2 = myMatcher.start(); idx2 < myMatcher.end(); idx2++)
            matched[idx2] = true;
    }

    boolean allMatched = true;
    for(boolean charMatched : matched)
        allMatched &= charMatched;

    return allMatched;
}

有没有办法让这些代码更好,更快,更可读?

2 个答案:

答案 0 :(得分:2)

我有2个答案,虽然我不确定我是否理解这个问题。

  1. 调用Pattern.matcher(str2match).matches()方法而不是find()。在一次拍摄中,真实的返回值将告诉您整个字符串是否匹配。
  2. 将reg exp加上“^”(字符串的开头),并在“Pattern.compile(str)”前面添加一个“$”(字符串的结尾) - 正则表达式。
  3. 这两种解决方案也可以结合在一起。下面是一个示例类 - 您可以将其复制到AllMatch.java中,使用“javac AllMatch.java”编译它并将其作为“java AllMatch”运行(我假设您的CLASSSPATH中有“。”)。只需选择你觉得更优雅的解决方案:)新年快乐!

    import java.util.regex.Pattern;
    

    公共类AllMatch {

    private Pattern pattern;
    
    public AllMatch (String reStr) {
        pattern = Pattern.compile ("^" + reStr + "$");
    }
    
    public boolean checkMatch (String s) {
        return pattern.matcher(s).matches();
    }
    
        public static void main (String[] args) {
        int n = args.length;
        String  rexp2Match = (n > 0) ? args[0] : "(abc)+",
            testString = (n > 1) ? args[1] : "abcabcabc",
            matchMaker = new AllMatch (rexp2Match)
                    .checkMatch(testString) ? "" : "un";
        System.out.println ("[AllMatch] match " + matchMaker +
                    "successful");
        }
    

    }

答案 1 :(得分:1)

这有效:

private static boolean fullyCovered(final String input,
    final Pattern pattern)
{
    // If the string is empty, check that it is matched by the pattern
    if (input.isEmpty())
        return pattern.matcher(input).find();

    final int len = input.length();
    // All initialized to false by default
    final boolean[] covered = new boolean[len];

    final Matcher matcher = pattern.matcher(input);

    for (int index = 0; index < len; index++) {
        // Try and match at this index:
        if (!matcher.find(index)) {
            // if there isn't a match, check if this character is already covered;
            // if no, it's a failure
            if (!covered[index])
                return false;
            // Otherwise, continue
            continue;
        }
        // If the match starts at the string index, fill the covered array
        if (matcher.start() == index)
            setCovered(covered, index, matcher.end());
    }

    // We have finished parsing the string: it is fully covered.
    return true;
}

private static void setCovered(final boolean[] covered,
    final int beginIndex, final int endIndex)
{
    for (int i = beginIndex; i < endIndex; i++)
        covered[i] = true;
}

执行起来可能不会更快,但我猜测它更容易阅读;)另外,.find(int)重置匹配器,所以这是安全的。