执行此操作的正确方法是使用正则表达式来匹配整个 unicode 定义并使用组替换。
匹配 unicode-string 的正则表达式:
一个 unicode 字符看起来像 \uABCD,所以是 \u,后跟一个 4 个字符的十六进制数字字符串。匹配这些可以使用
\\u[A-Fa-f\d]{4}
但是这样做有一个问题:
在像“只是一些 \\uabcd 任意文本”这样的 String 中,\u 仍然会匹配。所以我们需要确保\u前面有偶数个\s:
(?<!\\)(\\\\)*\\u[A-Fa-f\d]{4}
现在作为输出,我们需要一个反斜杠,后跟一个十六进制数字部分。这可以通过组替换来完成,所以让我们开始对字符进行分组:
(?<!\\)(\\\\)*(\\u)([A-Fa-f\d]{4})
作为替换,我们希望组中的所有反斜杠匹配两个反斜杠,后跟一个反斜杠和 unicode-literal 的十六进制部分:
$1\\$3
现在是实际代码:
String pattern = "(?<!\\\\)(\\\\\\\\)*(\\\\u)([A-Fa-f\\d]{4})";
String replace = "$1\\\\$3";
Matcher match = Pattern.compile(pattern).matcher(test);
String result = match.replaceAll(replace);
这是很多反斜杠!嗯,java、regex 和反斜杠存在一个问题:java 和 regex 中需要对反斜杠进行转义。所以“\\\\”作为java中的模式字符串匹配一个\作为正则表达式匹配的字符。
编辑:
在实际的字符串中,字符需要被过滤掉并用它们的整数表示来替换:
StringBuilder sb = new StringBuilder();
for(char c : in.toCharArray())
if(c > 127)
sb.append("\\").append(String.format("%04x", (int) c));
else
sb.append(c);
这假设“unicode-character”是指非 ASCII 字符。此代码将按原样打印任何 ASCII 字符,并将所有其他字符输出为反斜杠,后跟其 unicode 代码。不过,“unicode-character”的定义相当模糊,因为 java 中的 char 总是代表 unicode-characters。这种方法保留了任何控制字符,如“\n”、“\r”等,这就是我选择它而不是其他定义的原因。