【问题标题】:Detecting High Surrogates in a String using Regular Expressions使用正则表达式检测字符串中的高代理项
【发布时间】:2011-08-01 02:31:31
【问题描述】:

我想检查一个字符串是否包含任何高代理。在 Java 中,我会使用 Character.isHighSurrogate(c) 并且可以。

在正则表达式中(使用 Android 2.3.3 SDK 提供的实现),我期待它可以工作:

[\uD800-\uDBFF]

但事实并非如此。

我正在使用字符:???? (代码点:177700)对此进行测试(适用于我的 java 检查,但不适用于正则表达式检查)。

有什么想法吗?

【问题讨论】:

    标签: java android regex unicode utf-8


    【解决方案1】:

    正则表达式引擎查看代码points而不是代码units它别无选择,因为这是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 满足所有 1 级要求以及一些 2 级要求,例如完整属性(即将到来的 2.7)、字形和更高级的边界。在 JDK7 之前你无法达到 1 级,即使在那里它也缺少其余的。没有字素支持很难使用 Unicode,没有代码点支持也是不可能的。

    有时您可以通过这些东西找到孤立的替代物或反向替代物,但这些不应该出现在对交换有效的数据中。

    一般来说,您希望尽可能远离任何代码单元接口,而只使用那些支持代码点接口的 API。代码单元是一个诅咒。

    此外,请远离 Java 预处理器。这样你不会从你的正则表达式中得到快乐。 ICU 正则表达式引擎同时支持\x{ᴄᴏᴅᴇ ᴘᴏɪɴᴛ}\N{ᴄʜᴀʀɴᴀᴍᴇ},所以你应该使用它们。

    你为什么要胡闹那些讨厌的代码units呢?它们违反了代码点抽象。

    【讨论】:

    • 非常好,非常感谢。我使用代码单元(即 [\uD800-\uDBFF])的唯一原因是因为我看不到任何专门匹配代码点的方法(在 Android SDK 的 Pattern 文档中)。出于兴趣,我想它永远无法与 \p{inHighSurrogates} 匹配,因为 High Surrogate “总是”是代码点的一半?好吧,我想它会匹配高代理而不是低代理的情况......?
    【解决方案2】:

    查看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”,这意味着两种命名样式都有效,并且可以正确检测低代理项。

    奇怪的是,相同的代码不适用于高代理,即以下行都打印错误:

    System.out.println(Pattern.compile("\\p{InHighSurrogates}").matcher(test).find());
    System.out.println(Pattern.compile("\\p{InHIGH_SURROGATES}").matcher(test).find());
    

    【讨论】:

      猜你喜欢
      • 2010-12-04
      • 1970-01-01
      • 1970-01-01
      • 2012-08-16
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多