为什么空正则表达式和空捕获组正则表达式返回字符串长度加一个结果

时间:2013-04-19 11:16:01

标签: java regex string

您如何解释空正则表达式和空捕获组正则表达式返回字符串长度加一个结果?

代码

public static void main(String... args) {
    {
        System.out.format("Pattern - empty string\n");
        String input = "abc";
        Pattern pattern = Pattern.compile("");
        Matcher matcher = pattern.matcher(input);
        while (matcher.find()) {
            String s = matcher.group();
            System.out.format("[%s]: %d / %d\n", s, matcher.start(),
                    matcher.end());
        }
    }
    {
        System.out.format("Pattern - empty capturing group\n");
        String input = "abc";
        Pattern pattern = Pattern.compile("()");
        Matcher matcher = pattern.matcher(input);
        while (matcher.find()) {
            String s = matcher.group();
            System.out.format("[%s]: %d / %d\n", s, matcher.start(),
                    matcher.end());
        }
    }
}

输出

Pattern - empty string
[]: 0 / 0
[]: 1 / 1
[]: 2 / 2
[]: 3 / 3
Pattern - empty capturing group
[]: 0 / 0
[]: 1 / 1
[]: 2 / 2
[]: 3 / 3

2 个答案:

答案 0 :(得分:5)

正则表达式引擎被硬编码为在零长度匹配时前进一个位置(否则为无限循环)。您的正则表达式匹配零长度子字符串。每个字符之间都有零长度的子串(想想“每个字符之间的间隙”);此外,正则表达式引擎也会考虑字符串有效匹配位置的开始和结束。因为长度为N的字符串在字母之间包含N+1个间距(计算正则表达式引擎所做的开始和结束),您将获得N+1个匹配。

答案 1 :(得分:4)

正则表达式引擎也会考虑字符前后的位置。你可以看到这样的事实,即它们有^(字符串的开头),$(字符串的结尾)和\b字边界,它们在某些位置匹配而不匹配任何字符(因此在字符之间/之前/之后)。因此,我们在必须考虑的字符之间有N-1个位置,以及第一个和最后一个位置(因为^$会分别匹配),这会给你N + 1个候选人位置。所有这些都匹配完全不受限制的空模式。

所以这是你的比赛:

" a b c "
 ^ ^ ^ ^

对于N个字符,显然是N + 1。

对于允许零长度匹配的其他模式,您将获得与您的模式中实际上找不到更长的模式相同的行为。例如,尝试\d*。它在输入字符串中找不到任何数字,但*将很乐意返回零长度匹配。