替换Unicode控制字符

8
我需要在Java中替换字符串中的所有特殊控制字符。
我想要向Google Maps API v3提问,但是Google似乎不喜欢这些字符。
例如:http://www.google.com/maps/api/geocode/json?sensor=false&address=NEW%20YORK%C2%8F 此URL包含此字符:http://www.fileformat.info/info/unicode/char/008f/index.htm 因此,当我收到一些数据并需要将其进行地理编码时,我知道某些字符无法通过地理编码,但我不知道确切的列表。
我无法找到有关此问题的任何文档,因此我认为Google不喜欢的字符列表如下:http://www.fileformat.info/info/unicode/category/Cc/list.htm 是否有任何已构建的函数可以摆脱这些字符,还是我必须构建一个新函数,逐个进行替换?
还是有一个好的正则表达式可以完成这项工作吗?
有人知道Google不喜欢哪个确切的字符列表吗?
编辑:Google已经为此创建了一个网页:https://developers.google.com/maps/documentation/webservices/?hl=fr#BuildingURLs

你能否手动删除URL中的%C2%8F部分,以查看该URL是否有效? - Paul Jowett
我可以手动替换所有无效字符。问题是我不知道全部的列表(也不想一个一个测试),而且我也不想为每个无效字符都执行 replaceAll。 - Cyril Gandon
1个回答

14

如果您想删除其他/控制Unicode类别中的所有字符,可以像这样操作:

    System.out.println(
        "a\u0000b\u0007c\u008fd".replaceAll("\\p{Cc}", "")
    ); // abcd

注意,这实际上会从字符串中删除(包括其他字符)Unicode字符'\u008f',而不是转义形式"%8F"的字符串。
如果黑名单不能很好地被一个Unicode块/类别捕获,Java确实有一个强大的字符类算术,具有交集、减法等功能,您可以使用。或者,你也可以采用否定的白名单方法,即不明确指定哪些字符是非法的,而是指定哪些是合法的,那么其他所有内容都将变得非法。
API链接
- java.util.regex.Pattern - regular-expressions.info/Character Class

示例

这是一个减法示例:

    System.out.println(
        "regular expressions: now you have two problems!!"
            .replaceAll("[a-z&&[^aeiou]]", "_")
    );
    //   _e_u_a_ e___e__io__: _o_ _ou _a_e __o __o__e__!!

[…] 是一个 字符类。例如 [aeiou] 匹配任何一个小写元音字母。 [^…] 是一个 否定的 字符类。 [^aeiou] 匹配任何一个 除了 小写元音字母以外的字符。

[a-z&&[^aeiou]] 匹配 [a-z] 减去 [aeiou],也就是所有小写辅音字母。

下一个例子展示了否定白名单的方法:

    System.out.println(
        "regular expressions: now you have two problems!!"
            .replaceAll("[^a-z]", "_")
    );
    //   regular_expressions__now_you_have_two_problems__

只有小写字母a-z是合法的,其他所有字符都是非法的。


问题在于我将使用中文、阿拉伯语和所有可能的 UTF-8 字符:) 我将尝试使用 p{Cc} !! - Cyril Gandon
@Scorpi0:以上只是示例。找到您想要黑/白名单的任何Unicode类别/块,并使用此处显示的元素按您希望的方式组成正则表达式。 - polygenelubricants
1
哦,\p{Cc},又一个未记录的模式表达式。不错,值得知道。 - BalusC
2
@BalusC:我不是Unicode专家,但我认为它已经被记录下来了:“类别可以用可选前缀Is指定:\p{L}\p{IsL}都表示Unicode字母的类别。” 将“L”替换为“Cc”或任何其他类别名称。 - polygenelubricants
1
在Linux上使用Oracle Java 1.6.0_29时,"\p{Cc}"对我无效,但是"\p{C}"有效(小写字母"c"不需要)。我不知道为什么。 - gnobal

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