未公开的Java正则表达式字符类:\ p {C}
我在Java项目中发现了一个有趣的正则表达式: "[\\p{C}&&\\S]"
我知道方法的&&
意思是“设置交集”,并且\S
是“非空白”,但是
该java.util.regex.Pattern中的文件没有提到它。列表上唯一类似的类是\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 `????`
}
}
我在任何地方都发现的唯一提及是在这里:
\ p {C}或\ p {Other}:不可见的控制字符和未使用的代码点。
但是,\p{Other}
在Java中似乎并不存在,并且未使用匹配的代码点。
我的Java版本信息:
$ java -versionjava 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支持下的Pattern文档中,我们发现以下内容:
此类符合Unicode技术标准#18的级别1
:Unicode正则表达式以及RL2.1规范等效项。
…
:\ p {L}和\ p
{IsL}都表示Unicode字母的类别。与脚本和块相同,也可以使用关键字general_category(或其简称gc)指定类别,如general_category
= Lu或gc = Lu。
支持的类别是Character类指定的版本中的Unicode标准类别。类别名称是标准中定义的名称,包括规范性的和信息性的。
从Unicode技术标准#18中,我们发现已将C
其定义为与任何其他General_Category值匹配,并且对此值的支持是对1级一致性的要求的一部分。Java
\p{C}
之所以实现,是因为它声称符合UTS#18的级别1。
它可能 应该 支持\p{Other}
,但显然不支持。
更糟糕的是,这违反了1级一致性所要求的RL1.7,这要求匹配是通过代码点而不是代码单元进行的:
为了满足此要求,实现应处理所有范围的Unicode代码点,包括从U + FFFF到U + 10FFFF的值。
不应该有任何的比赛\p{C}
在您的测试字符串,因为您的测试字符串应与General_Category
=所以,(其它符号)一个表情符码点进行匹配,而不是作为两个代理人。
以上是 未公开的Java正则表达式字符类:\ p {C} 的全部内容, 来源链接: utcz.com/qa/435786.html