当前位置: 首页 > 知识库问答 >
问题:

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

穆浩皛
2023-03-14

为什么此模式无法编译:

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正则表达式编译器中的错误,还是我遗漏了什么?我喜欢在详细的正则表达式中使用[],而不是反斜杠,因为这样可以节省一些视觉噪音。但显然他们不一样!

附言:这个问题与反斜线无关。它是关于使用包含单个空格的字符类在冗长正则表达式中转义空格,而不是使用反斜杠。

详细正则表达式(?x)和包含单个空格的字符类的组合会使编译器无法识别单词边界转义\b

使用Java进行测试,最高可达1.8.0_151

共有3个答案

皇甫飞飙
2023-03-14

由于自由间距(冗余)模式,(?x)中的空间被忽略,[],因此正则表达式引擎将您的正则表达式视为[]\\b
如果我们删除\\b,它将被视为[]我们将得到关于未关闭字符类的错误-字符类不能为空,因此直接放置在[之后的将被视为属于该类的第一个字符,而不是关闭字符类的元符号。

因此,由于[未关闭,正则表达式引擎将\b视为放置在该字符类中。但\b不能放置在该字符类中(它不表示字符,而是“位置”),因此我们看到了关于“不支持的转义序列”(在字符类中,但该部分被跳过)的错误。

换句话说,您不能在详细模式(至少在Java中)中使用[]来转义空间。您需要使用“\\”“[\\]”

毛缪文
2023-03-14

这是模式类中Java的peekPastWhitespace()方法中的一个错误。追踪整个问题。。。我决定看看OpenJDK 8-b132的模式实现。让我们从顶部开始敲打:

  1. compile()在第1696行调用expr()
  2. expr()在第1996行调用sequence()
  3. sequence()在第2063行调用clazz(),因为满足了[的情况
  4. clazz()在第2509行调用peek()
  5. peek()
  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;
}

parsePastWhitespace()方法中也存在相同的错误。

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

你能做些什么来解决这个问题:

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

酆华皓
2023-03-14

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

“[]”“\\”或甚至与相同。

问题在于开始启用注释模式时的(?x)。正如文件所述

允许模式中的空白和注释。
在这种模式下,空白被忽略,以#开头的嵌入注释被忽略,直到一行结束。
注释模式也可以通过嵌入标志表达式(?x)

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

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

 类似资料:
  • 问题内容: 我想在Elastisearch中使用单词边界进行正则表达式查询,但是看起来Lucene正则表达式引擎不支持。我可以使用哪些解决方法? 问题答案: 在ElasticSearch regex风格中,没有直接等效于单词边界的功能。最初是一样的东西,如果用一个字字符开始,并且尾部就像如果用一个字字符结束。 因此,我们需要确保在字符串的前后或字符串的开始/结束处有一个非单词char 。由于正则表

  • 我正在使用以下正则表达式: 我的目标是只验证数字(int和decimal),空格, ( ), 点,AND,OR。其他一切都是不允许的。它看起来像是工作的,但是我对单词边界\bAND\b和\bOR\b Eg有问题。我不能输入ANDWE或EEE或任何组合,但我能做的是AN或A。如何在字符串中只允许两个单词AND或OR?它们在字符串中是可选的。 输入示例 0.10和23-有效 12和(15或0.2)-有

  • 我试图找到一个Java正则表达式,即使在输入文本中有一个\n时,它也能匹配一个单词。请注意\n应该显示为原始字符串。我使用的是典型的单词边界https://regex101.com/r/Se5iVW/1。 例如 在这里,我期望有5个匹配项(前四个匹配项和最后一个匹配项)。

  • 使用正则表达式匹配表达式 为什么这两个示例匹配如下(突出显示): c# < code>a #b #c #d 具体来说,为什么第一个字符串不匹配包含最后一个#之前的所有内容? 由于单词边界(\b)是零宽度匹配,可以在单词字符(\w)和非单词字符(\ w)之间匹配,或者在单词字符和字符串的开始或结束之间匹配,我不确定以非单词字符结束表达式会如何影响匹配。

  • 问题内容: 我目前正在编写一个用于匹配内容中特定单词的库。 本质上,它的工作方式是将单词编译为正则表达式,然后通过所述正则表达式运行内容。 我要添加的功能是指定要匹配的给定单词是否必须以单词开头和/或结尾。例如,我有这个词。我指定它 必须开始一个字 ,因此将 匹配 的是在开始,但 不能匹配 为不启动的话。 我想使用单词边界来执行此操作,但是在进行一些测试时,我发现它无法正常运行。 采取以下措施,

  • 问题内容: 在JavaScript中: 正确地给我: 当我使用utf-8字符时: 在字边界运营商似乎没有工作时: 这个问题有方法解决吗? 问题答案: 仅当一个单词字符之前或之后没有另一个单词字符(因此等于和)时,单词边界声明才匹配。并且定义为。因此与希腊字符不匹配。因此,您不能在这种情况下使用。 相反,您可以使用以下方法: