我的应用程序中有功能可以替换 json 中的一些文本(我在示例中简化了它)。它们的替换可能包含转义序列,如n b t
等,当我尝试使用 Jackson 构建 json 时,这些序列可能会破坏 json 字符串。所以我决定使用 Apache 的解决方案 -StringEscapeUtils.escapeJava()
转义所有转义序列。但Matcher.replaceAll()
删除了由escapeJava()
添加的反斜杠
有代码:
public static void main(String[] args) {
String json = "{"test2": "Hello toReplace \"test\" world"}";
String replacedJson = Pattern.compile("toReplace")
.matcher(json)
.replaceAll(StringEscapeUtils.escapeJava("replacement n b t"));
System.out.println(replacedJson);
}
预期输出:
{"test2": "Hello replacement n b t "test" world"}
实际输出:
{"test2": "Hello replacement n b t "test" world"}
为什么Matcher.replaceAll()
会删除反冲,而System.out.println(StringEscapeUtils.escapeJava("replacement n b t"));
返回正确的输出 -replacement n b t
StringEscapeUtils.escapeJava("n")
允许您将单个换行符n
转换为两个字符:和
n
。
是模式替换中的一个特殊字符,来自 https://docs.oracle.com/javase/7/docs/api/java/util/regex/Matcher.html#replaceAll(java.lang.String):
请注意,替换字符串中的反斜杠 (
) 和美元符号 (
$
) 可能会导致结果与将其视为文本替换字符串的结果不同。如上所述,美元符号可以被视为对捕获的子序列的引用,反斜杠用于转义替换字符串中的文字字符。
要将它们作为文字字符,您需要通过Matcher.quoteReplacement
从 https://docs.oracle.com/javase/7/docs/api/java/util/regex/Matcher.html#quoteReplacement(java.lang.String) 转义它:
返回指定
String
的文本替换String
。此方法生成一个String
,该将用作Matcher
类的appendReplacement
方法中的文本替换s
。生成的String
将与被视为文本序列s
字符序列匹配。斜杠()和美元符号(
$
)将没有特殊的含义。
所以在你的情况下:
.replaceAll(Matcher.quoteReplacement(StringEscapeUtils.escapeJava("replacement n b t")))
如果你想在replaceAll
中使用文字反斜杠,你需要转义它。您可以在此处的文档中找到此信息
StringEscapeUtils.escapeJava
将转义适合在 Java 源代码中使用的字符串 - 但它不允许你在源代码中使用未转义的字符串。
"replacement n b t"
^ new line
^ backspace
^ tab
如果要在常规 Java 字符串中使用文字反斜杠,则需要:
"replacement \n \b \t"
因为这是一个 java 字符串,用于replaceAll
的正则表达式的替换部分,所以需要:
"replacement \\n \\b \\t"
尝试:
String replacedJson = Pattern.compile("toReplace")
.matcher(json)
.replaceAll("replacement \\n \\b \\t")
你也必须使用Matcher.quoteReplacement()
来逃避。
public static String replaceAll(String json, String regex, String replace) {
return Pattern.compile(regex)
.matcher(json)
.replaceAll(Matcher.quoteReplacement(StringEscapeUtils.escapeJava(replace)));
}