0

字符类交集运算符&&,根据其功能的定义,应该是可交换的。[a&&b]应该匹配与任何 a 和 b 完全相同的字符[b&&a]。我发现以下模式都满足这个标准。

[a-z&&abcd]如同[abcd&&a-z]

[a-z&&ab[cd]]如同[ab[cd]&&a-z]

[a-z&&[ab][cd]]如同[[ab][cd]&&a-z]

它们都等价于[abcd]。但是,如果表达[a-z&&[ab]cd],这不再是真的。该表达式仅匹配cand d,但不匹配aand b。但是,翻转版本[[ab]cd&&a-z]与其他模式一样匹配所有四个字符。换句话说

[[ab]cd&&a-z]不一样[a-z&&[ab]cd]

我进入的来源Pattern找出了为什么会这样,我发现这是实现交集的方式(Java 1.8.0_60 JDK)

case '&':
    // ...
    ch = next();
    if (ch == '&') {
        ch = next();
        CharProperty rightNode = null;
        while (ch != ']' && ch != '&') {
            if (ch == '[') {
                if (rightNode == null)
                    rightNode = clazz(true);
                else
                    rightNode = union(rightNode, clazz(true));
            } else { // abc&&def
                unread();
                rightNode = clazz(false); // here is what happens
            }
            ch = peek();
        }

请注意,标记的行是

rightNode = clazz(false);

并不是

rightNode = union(rightNode, clazz(true));

换句话说,在 的右侧&&,每当遇到不在嵌套字符类中的第一个字符时,模式解析器都会假定它之前没有任何内容。因此,在 之后&&,解析器读[ab]rightNode,然后读取cd,但不是与 合并[ab],而是覆盖它。

我知道实际上没有人写像 regex 这样的正则表达式[a-z&&[ab]cd],但是文档仍然暗示它应该可以工作。这是实现中的错误,还是实际上应该以这种方式工作?

4

0 回答 0