代码之家  ›  专栏  ›  技术社区  ›  Leo Aso

Java正则表达式交集(&&)不可交换

  •  0
  • Leo Aso  · 技术社区  · 5 年前

    字符类交集算子 && ,根据其功能的定义,应该是可交换的。 [a&&b] [b&&a] 对于任何a和b,我发现下面的模式都满足这个标准。

    [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] ,这不再是事实。这个表达式只匹配 c d a b . 但是,翻转的版本 [[ab]cd&&a-z]

    [[ab]cd&a-z] 不同于 [a-z&[ab]光盘]

    我调查了 Pattern 为了找出原因,我发现这就是intersection的实现方式(Java 1.8.0u60jdk)

    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 ,但不是与 [阿布] ,它只是覆盖了它。

    [a-z&[ab]光盘] 但是,文档仍然暗示它应该可以工作。这是实现中的一个bug,还是应该以这种方式工作?

    0 回复  |  直到 5 年前