在Java中使用正则表达式匹配基本多文种平面之外的字符

19

我该如何在Java中匹配位于Unicode基本多文种平面之外的字符(以便移除它们)?

2个回答

27

为了删除所有的非基本多文种字符(non-BMP characters),可以尝试以下方法:

String sanitizedString = inputString.replaceAll("[^\u0000-\uFFFF]", "");

你实际上测试过这个吗?因为你的字符范围包括用于构造非基本多文种平面代码点的代理范围。 - Anon
3
正如您在自己的回答中指出的那样,正则表达式是在代码点级别而不是代码单元级别上进行评估的,因此它无法识别代理项。 - axtavt
1
是的,这已经测试过非BMP字符。 - James Van Huis
1
@Anon - 关于Java中的补充字符的更多信息: http://java.sun.com/developer/technicalArticles/Intl/Supplementary/ - James Van Huis
警告:这种替代可能通过匹配以前未配对的代理项而引入新的天体字符,这可能或可能不符合原始问题的要求:尝试 String inputString = "\uD800\uD800\uDC00\uDC00"; - user1089451
显示剩余2条评论

4

您是在寻找特定字符还是所有位于BMP之外的字符呢?

如果是前者,您可以使用StringBuilder构造一个包含来自高平面的代码点的字符串,然后正则表达式将按预期工作:

  String test = new StringBuilder().append("test").appendCodePoint(0x10300).append("test").toString();
  Pattern regex = Pattern.compile(new StringBuilder().appendCodePoint(0x10300).toString());

  Matcher matcher = regex.matcher(test);
  matcher.find();
  System.out.println(matcher.start());

如果您想从字符串中删除所有非BMP字符,则我建议直接使用StringBuilder而不是正则表达式:

  StringBuilder sb = new StringBuilder(test.length());
  for (int ii = 0 ; ii < test.length() ; )
  {
     int codePoint = test.codePointAt(ii);
     if (codePoint > 0xFFFF)
     {
        ii += Character.charCount(codePoint);
     }
     else
     {
        sb.appendCodePoint(codePoint);
        ii++;
     }
  }

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接