编译具有字符类和单词边界的详细 Java 正则表达式时出错

2022-09-01 00:31:49

为什么这个模式无法编译:

Pattern.compile("(?x)[ ]\\b");

错误

ERROR java.util.regex.PatternSyntaxException:
Illegal/unsupported escape sequence near index 8
(?x)[ ]\b
        ^
at java_util_regex_Pattern$compile.call (Unknown Source)

虽然以下等效项有效?

Pattern.compile("(?x)\\ \\b");
Pattern.compile("[ ]\\b");
Pattern.compile(" \\b");

这是Java正则表达式编译器中的一个错误,还是我遗漏了什么?我喜欢在冗长的正则表达式中使用,而不是反斜杠 - 反斜杠 - 空间,因为它可以节省一些视觉噪音。但显然他们是不一样的![ ]

PS:这个问题不是关于反斜杠的。它是关于使用包含单个空格的字符类而不是使用反斜杠来转义详细正则表达式中的空格。[ ]

不知何故,详细正则表达式和包含单个空格的字符类的组合会丢弃编译器,并使其无法识别单词边界转义(?x)[ ]\b


使用 Java 进行了高达 1.8.0_151 的测试


答案 1

我喜欢在冗长的正则表达式中使用,而不是反斜杠 - 反斜杠 - 空间,因为它可以节省一些视觉噪音。但显然他们是不一样的![ ]

"[ ]"与 相同甚至相同。"\\ "" "

问题是在开始时启用注释模式。如文档所述(?x)

允许在模式中使用空格和注释。
在此模式下,将忽略空格,并忽略以 开头的嵌入注释,直到行尾。
注释模式也可以通过嵌入式标志表达式启用。#(?x)

在注释模式下,正则表达式与正则表达式相同,并且不会编译,因为空字符类不会解析为空,而是像(包含文本的未关闭字符类)一样进行解析。"(?x)[ ]\\b""[]\\b"[]"[\\]"]

请改用。或者,在注释模式下保留空间,方法是使用反斜杠转义:或 。" \\b""(?x)[\\ ]\\b""(?x)\\ \\b"


答案 2

这是类中 Java 方法中的一个错误。向下跟踪整个问题...我决定看看OpenJDK 8-b132的模式实现。让我们从顶部开始锤击它:peekPastWhitespace()Pattern

  1. compile()拨打1696expr()
  2. expr()拨打1996电话sequence()
  3. sequence()拨打2063电话,因为遇到的情况clazz()[
  4. clazz()拨打2509线peek()
  5. peek()调用行 1830,因为计算结果为 (由于在模式的开头添加了标志)peekPastWhitespace()if(has(COMMENTS))truex(?x)
  6. peekPastWhitespace()(发布在下面)跳过模式中的所有空格。

peekPastWhitespace()

private int peekPastWhitespace(int ch) {
    while (ASCII.isSpace(ch) || ch == '#') {
        while (ASCII.isSpace(ch))
            ch = temp[++cursor]
        if (ch == '#') {
            ch = peekPastLine();
        }
    }
    return ch;
}

解析PastWhitespace() 方法中存在相同的错误。

您的正则表达式被解释为 ,这是导致错误的原因,因为 Java 中的字符类不支持正则表达式。此外,一旦你解决了这个问题,你的字符类也没有关闭。[]\\b\b\b]

您可以采取哪些措施来解决此问题:

  1. \\ 如OP所述,只需使用双反斜杠和空格
  2. [\\ ]转义字符类中的空格,以便按字面解释
  3. [ ](?x)\\b将内联修饰符放在字符类之后