Java 7、正则表达式和补充 unicode 字符

标签 java regex unicode supplementary

有问题的字符串有一个补充的 unicode 字符“\ud84c\udfb4”。根据 javadoc,正则表达式匹配应该在代码点级别而不是字符级别完成。但是,下面的拆分代码将低代理项 (\udfb4) 视为非单词字符并对其进行拆分。

我错过了什么吗?完成非单词字符拆分的其他替代方法是什么? (Java 版本“1.7.0_07”)

提前致谢。

Pattern non_word_regex = Pattern.compile("[\\W]", Pattern.UNICODE_CHARACTER_CLASS);
String a = "\u529f\u80fd\u0020\u7d76\ud84c\udfb4\u986f\u793a\u5ee3\u544a";
String b ="功能 絶𣎴顯示廣告";
System.out.print("original "+a+"\norginal hex ");
for(char c : a.toCharArray()){
    System.out.print(Integer.toHexString((int)c));
    System.out.print(' ');
}
System.out.println();

String[] tokens = non_word_regex.split(a);

for(int i =0; i< tokens.length; i++){
   String token = tokens[i];
   System.out.print(i+" ");
   for(char c : token.toCharArray()){
       System.out.print(Integer.toHexString((int)c));
       System.out.print(' ');
   }
   System.out.println();
}

输出:
原创功能绝𣎴显示广告
原始十六进制 529f 80fd 20 7d76 d84c dfb4 986f 793a 5ee3 544a
0 529f 80fd
1 7d76 d84c
2 986f 793a 5ee3 544a

最佳答案

这看起来就像正则表达式引擎中的错误。如果您使用 \w 表达式,一切都正确匹配,𣎴 仍然是由两个字符组成的单个代码点。这可以通过运行以下代码轻松验证:

Pattern pattern = Pattern.compile("(?U)[\\w]");
String str = "功能 絶𣎴顯示廣告";

Matcher matcher = pattern.matcher(str);
while (matcher.find()) {
    System.out.println(matcher.toMatchResult().group());
}

我刚刚调查过了,所以我可以告诉你问题出在哪里。如果您查看 java.util.regex.Pattern 中的方法 compile() (从第 1625 行开始),您将看到扫描正则表达式以查找补充字符并决定是否支持扫描的代码。

这种方法的问题是代码没有考虑到这样一个事实,即即使正则表达式没有补充字符,它可能仍然想要匹配它们,例如,就像您的情况一样。

解决方案 是设计一些包含增补字符 的正则表达式,但它们不会影响匹配过程。我建议你使用像这样无辜的东西:

Pattern nonWordRegex = Pattern.compile("(?U)(?!\uDB80\uDC00)[\\W]");

(?!\uDB80\uDC00) 部分起到了作用。这是对补充字符私有(private)范围内字符的否定前瞻,这意味着您很可能不会在文本中找到它。瞧:正则表达式引擎认为模式中有增补字符,并启用它们的支持!

关于Java 7、正则表达式和补充 unicode 字符,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/20502608/

相关文章:

unicode - 使用iTerm2,如何输入带有重音符号的字符?

mysql - 玛丽亚数据库/MySQL : replacing an unicode character by another one doesn't work (0 rows affected)

java - 在循环中创建 JButton 会导致仅出现最后一个

java - 黑莓 - 模拟器上的安全 API 错误

Java正则表达式匹配函数内的参数

Java - 正则表达式匹配多个单词

java - 如何从 JMenuItem (Java Swing) 中删除空图标间隙?

java - @GenerateValue 注解中生成器属性的意义

ruby - 什么是匹配不在行尾的字符串的正则表达式?

ruby - 按字素拆分 Unicode 实体