私はいくつかのApacheライブラリをすばやく見て、同じ問題に対処しました。興味深いことに、EMCAScript言語仕様をフォローアップしたところ、unescape()関数の疑似コードが見つかりました。あなたはそれが一緒に、この単純化の実装(下記参照)と少なくとも例えばあなたの質問では、出力の一致を置くことは簡単ですhttps://tc39.github.io/ecma262/#sec-unescape-string
でこれを見ることができます。
このコードは最適化されていませんが、文字エンコーディングが関連するかどうかについては考えていませんが、Regexを使って物事を取り締まるよりもあまり苦労しないかもしれません。
public static String unescape(String s) {
StringBuilder r = new StringBuilder();
for (int i = 0; i < s.length();) {
if (s.charAt(i) == '%') {
if (looksLikeUnicode(s, i)) {
r.append((char) fromHex(s, i + 2, i + 5));
i += 6;
continue;
}
if (looksLikeAscii(s, i)) {
r.append((char) fromHex(s, i + 1, i + 2));
i += 3;
continue;
}
}
r.append(s.charAt(i));
i += 1;
}
return r.toString();
}
private static boolean looksLikeUnicode(String s, int i) {
return (i + 5 < s.length()) && (s.charAt(i + 1) == 'u') && areHexDigits(s, i + 2, i + 5);
}
private static boolean looksLikeAscii(String s, int i) {
return (i + 2 < s.length()) && areHexDigits(s, i + 1, i + 2);
}
private static boolean areHexDigits(String s, int from, int to) {
for (int i = from; i <= to; ++i) {
if (isNotHexDigit(s.charAt(i))) {
return false;
}
}
return true;
}
private static boolean isHexDigit(char c) {
return (c >= '0' && c <= '9') || (c >= 'A' && c <= 'F') || (c >= 'a' && c <= 'f');
}
private static boolean isNotHexDigit(char c) {
return !isHexDigit(c);
}
private static int fromHex(String s, int from, int to) {
return Integer.parseInt(s.substring(from, to + 1), 16);
}
ブリリアント!どうもありがとうございます! ECMAScriptについて言及したら、実際にはJavaのネイティブScriptingEngineを使用して、JSスタイルのエスケープを行うことができることに気付きました。つまり、 'new ScriptEngineManager()。getEngineByName(" nashorn ")eval(" unescape(\ "%3C%=%20name %20 %% 3E \ ")") '、しかしそれはスクリプトエンジンをインスタンス化するための不必要なオーバヘッドをもたらすので、これを受け入れられた答えとしてマークしています。 – ccpizza
ニース。私はスクリプティングエンジンを考えていたはずです。より強力なソリューションですが、少し重いです。 –