java - 未记录的 Java 正则表达式字符类 :\p{C}

标签 java regex unicode

我在一个 Java 项目中发现了一个有趣的正则表达式:"[\\p{C}&&\\S]"

我理解 && 的意思是“设置交集”,而 \S 是“非空白”,但是 什么是 \p{ C},还能用吗?

java.util.regex.Pattern documentation没有提到它。列表中唯一类似的类是 \p{Cntrl},但它们的行为不同:它们都匹配控制字符,但 \p{C} 匹配 在 U+FFFF 以上的 Unicode 字符上两次,例如 PILE OF POO:

public class StrangePattern {
    public static void main(String[] argv) {

        // As far as I can tell, this is the simplest way to create a String
        // with code points above U+FFFF.
        String poo = new String(Character.toChars(0x1F4A9));

        System.out.println(poo);  // prints `💩`
        System.out.println(poo.replaceAll("\\p{C}", "?"));  // prints `??`
        System.out.println(poo.replaceAll("\\p{Cntrl}", "?"));  // prints `💩`
    }
}

我在任何地方发现的唯一提及是here :

\p{C} or \p{Other}: invisible control characters and unused code points.

但是,\p{Other}在Java中好像不存在,匹配的码位也没有使用。

我的 Java 版本信息:

$ java -version
java version "1.8.0_92"
Java(TM) SE Runtime Environment (build 1.8.0_92-b14)
Java HotSpot(TM) 64-Bit Server VM (build 25.92-b14, mixed mode)

额外问题:原始模式 "[\\p{C}&&\\S]" 的可能意图是什么?它发生在一个在电子邮件中发送之前验证字符串的方法中:如果该模式匹配,则会引发消息“无效字符串”的异常。

最佳答案

在 Unicode Support 下的 Pattern 文档中,我们发现以下内容:

This class is in conformance with Level 1 of Unicode Technical Standard #18: Unicode Regular Expression, plus RL2.1 Canonical Equivalents.

...

Categories may be specified with the optional prefix Is: Both \p{L} and \p{IsL} denote the category of Unicode letters. Same as scripts and blocks, categories can also be specified by using the keyword general_category (or its short form gc) as in general_category=Lu or gc=Lu.

The supported categories are those of The Unicode Standard in the version specified by the Character class. The category names are those defined in the Standard, both normative and informative.

来自 Unicode Technical Standard #18 ,我们发现 C 被定义为匹配任何 Other General_Category 值,并且对此的支持是 1 级一致性要求的一部分。 Java 实现 \p{C} 因为它声称符合 UTS #18 的第 1 级。


它可能应该支持\p{Other},但显然不支持。

更糟糕的是,它违反了 RL1.7 ,对于 1 级一致性是必需的,这要求匹配发生在代码点而不是代码单元:

To meet this requirement, an implementation shall handle the full range of Unicode code points, including values from U+FFFF to U+10FFFF. In particular, where UTF-16 is used, a sequence consisting of a leading surrogate followed by a trailing surrogate shall be handled as a single code point in matching.

您的测试字符串中不应有 \p{C} 匹配项,因为您的测试字符串应作为单个表情符号代码点与 General_Category=So(其他符号)匹配,而不是作为两个代理人。

关于java - 未记录的 Java 正则表达式字符类 :\p{C},我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/44034232/

相关文章:

java - 正则表达式定义正则语言

Java 泛型 : Useing multiple generic types in one collection type

java - 日期解析魔法

javascript - 有条件地在 <li> 标签中换行并删除第一个字符

c++ - 使用 ICU (ICU4C) 读取 UTF-8 编码文件的缓冲区大小

php - mb_split 解析函数无法处理日语字符 UTF-8 文本?

regex - 替换 : "\p{Cntrl}" - "\P{Print}"

java - 计算2次之间的差异时补偿BST

使用 JAXB 进行 namespace 绑定(bind)的 Java feed XML

java - 在 Java 中从列表中提取子字符串