我想检查String是否包含任何High Surrogates。在Java中,我将使用Character.isHighSurrogate(c),这可行。
在正则表达式中(使用Android 2.3.3 SDK提供的实现),我希望这可以工作:
[\uD800-\uDBFF]
但事实并非如此。
我使用char :( codepoint:177700)来测试这个(在我的java检查中工作,但不是正则表达式检查)。
有什么想法吗?
答案 0 :(得分:6)
正则表达式引擎会查看代码点,而不是代码单位。它没有选择,因为这是UTS#18 Level 1 Unicode support的基本要求:
第1级:基本的Unicode支持。在此级别,正则表达式引擎提供对Unicode字符的支持作为基本逻辑单元。 (这与Unicode的实际序列化无关,如UTF-8,UTF-16BE,UTF-16LE,UTF-32BE或UTF-32LE。)这是有用的Unicode支持的最低级别。它没有考虑最终用户对字符支持的期望,但确实满足了大多数低级程序员的要求。此级别的正则表达式匹配结果与国家或语言无关。在此级别,正则表达式引擎的用户需要编写更复杂的正则表达式来执行完整的Unicode处理。
无论是在普通的JDK正则表达式引擎中,还是在Android正则表达式引擎中,JNI进入ICU regex library以获得比JDK提供的更好的Unicode支持,都是如此。除此之外,ICU还满足所有Level-1要求以及一些Level-2要求,例如完整属性(即将推出的2.7),字形和更高的边界。你没有在JDK7之前达到1级,即使在那里它也缺少其余的。没有字形支持就很难使用Unicode,没有代码点支持就不可能。
有时你可以通过这些东西找到孤立的代理或反向代理,但这些不应该出现在有效交换的数据中。
通常,您希望尽可能远离任何代码单元接口,并且只使用那些支持代码点接口的API。代码单元是一个诅咒。
此外,请远离Java预处理器。从那种方式来说,你的正则表达不会让你高兴。 ICU正则表达式引擎支持\x{ᴄᴏᴅᴇ ᴘᴏɪɴᴛ}
和\N{ᴄʜᴀʀɴᴀᴍᴇ}
,因此您应该使用它们。
为什么你要用邪恶的代码单位来捣乱呢?它们违反了代码点抽象。
答案 1 :(得分:0)
查看Pattern的文档,有一个匹配链接到Character.UnicodeBlock的希腊字符的示例
Unicode块和类别的类
\ p {InGreek}希腊语块中的一个字符(简单block)
该类中的可用常量包含LOW_SURROGATES,假设android上的正则表达式impl与jdk兼容,我尝试了以下代码:
String test = new String(Character.toChars(177700));
System.out.println(Pattern.compile("\\p{InLowSurrogates}").matcher(test).find());
System.out.println(Pattern.compile("\\p{InLOW_SURROGATES}").matcher(test).find());
两次打印“true”,意味着两种命名样式都有效,并且正确检测到低代理。
奇怪的是,相同的代码不适用于高代理,即以下行都打印为false:
System.out.println(Pattern.compile("\\p{InHighSurrogates}").matcher(test).find());
System.out.println(Pattern.compile("\\p{InHIGH_SURROGATES}").matcher(test).find());