2

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

代码

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
4

2 回答 2

5

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

于 2013-04-19T11:19:51.080 回答
4

正则表达式引擎也会考虑字符前后的位置。您可以从以下事实中看出这一点:它们具有^(字符串开头)、$(字符串结尾)和\b单词边界之类的内容,它们在某些位置匹配而不匹配任何字符(因此在字符之间/之前/之后)。因此,我们有必须考虑的字符之间的 N-1 个位置,以及第一个和最后一个位置(因为^$将分别匹配那里),这为您提供了 N+1 个候选位置。所有这些都匹配一个完全不受限制的空模式。

所以这里是你的比赛:

" a b c "
 ^ ^ ^ ^

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

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

于 2013-04-19T11:21:34.503 回答