如何在没有 Java 7 的情况下匹配正则表达式字符串中大于 \uFFFF 的 Unicode 代码点?

How to match Unicode code points greater then \uFFFF in regex string without Java 7?

这是我的正则表达式:

(?x)(?:[A-Za-z:_] | [\xC0-\xD6]| [\xD8-\xF6] | [\xF8-\x{2FF}] | [\x{370}-\x{37D}] | [\x{37F}-\x{1FFF}] | [\x{200C}-\x{200D}] | [\x{2070}-\x{218F}] | [\x{2C00}-\x{2FEF}] | [\x{3001}-\x{D7FF}] | [\x{F900}-\x{FDCF}] | [\x{FDF0}-\x{FFFD}] | [\x{10000}-\x{EFFFF}])

Java 拒绝编译它。它引发了这个异常:

java.util.regex.PatternSyntaxException: Illegal hexadecimal escape sequence near index 68
^/((?:(?x)(?:(?x)(?:[A-Za-z:_] | [\xC0-\xD6]| [\xD8-\xF6] | [\xF8-\x{2FF}]...
                                                                    ^

怎么了?

Java 6

BNF 图仅适用于 Java 7 及以上。对于 Java 6,Java RegExp,\x 期望后面正好有两个十六进制数字,不多也不少。如果需要匹配 Unicode,请使用 \u 后跟四个十六进制数字。

在你的情况下,那将是 ... [\xF8-\u02FF] ...,等等

原因是 Java RegExp 不使用模式作为字符的占位符。相反,Java 编译器创建 Unicode 代码点并将它们收集在 Unicode 字符串中,然后将其传递给 RegExp 工具。因此,RegExp 工具永远不会看到 \x\u(这也是您收到此注释的编译错误的原因:// See c:\User\...

对于 Unicode 代码点 > 0xFFFF,您需要使用 surrogate pairs。您可以使用 Character.toChars() 创建它们。 Character.toChars(0x10000) 创建两个 char 代表 \x{10000}.

\x{<i>h...h</i>} 表示法,带有大括号和非固定数目的十六进制数字,直到 Java 才添加到 java.util.regex.Pattern 7:

(在页面中搜索\x{。只有后者link有。)

相反,您需要使用 \u<i>hhhh</i> 表示法:[\xF8-\u02FF].

然而,\u<i>hhhh</i>表示一个UTF-16编码单元,即Javachar ,而不是完整的 Unicode 代码点,因此正则表达式的最后一部分 — [\x{10000}-\x{EFFFF}] — 翻译起来比较棘手。我认为 Java 6 正则表达式完全在代码单元上运行,因此您实际上需要将其视为两个代码单元:[\uD800-\uDB7F][\uDC00-\uDFFF](其中 [\uD800-\uDB7F] 是 "high" 代理项,而 [\uDC00-\uDFFF] 是 "low" 代理项的整个范围;幸运的是 U+EFFFF 恰好位于具有相同高代理项的代码点范围的末尾,否则你会需要做一些更复杂的事情)。 (免责声明: 未经测试。)

以下是我解决问题的方法:

String regex = "(?x)" + 
       "(?:" + 
       "[A-Za-z:_]        |" + 
       "[\xC0-\xD6]     |" + 
       "[\xD8-\xF6]     |" + 
       "[\xF8-\u02FF]   |" + 
       "[\u0370-\u037D] |" + 
       "[\u037F-\u1FFF] |" + 
       "[\u200C-\u200D] |" + 
       "[\u2070-\u218F] |" + 
       "[\u2C00-\u2FEF] |" + 
       "[\u3001-\uD7FF] |" + 
       "[\uF900-\uFDCF] |" + 
       "[\uFDF0-\uFFFD] |" + 
       "[\ud800\udc00-\udb7f\udfff]" + 
 )";

感谢大家的帮助。

参考: