Matcher.replaceAll() 删除了反斜杠,即使我转义了它.爪哇岛



我的应用程序中有功能可以替换 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)));
}

最新更新