replaceAll 与 lambda 回调未按预期工作

问题描述

我对 Java-Fu 有点生疏,但我遇到了一个我不太明白的问题。

我有一个字符串 test\\"escape\"test\,我正在尝试将其转换为 test\"escape"test\(这是在字符串转义之前)。

我发现了这个带有函数回调的漂亮 replaceAll 方法,我试图从所有以反斜杠开头并以 qoute 结尾的子字符串中删除恰好一个反斜杠(例如 {{1 }} 到 \\",但任何其他出现的反斜杠都不应修改)。

不幸的是,我返回了 \",位置 5 处的反斜杠比预期少了一个

这是我试过的代码

test"escape"test\

在这里遗漏了什么?

解决方法

您的代码的问题在于您在 lambda 中传递的字符串被视为替换模式,其中 \ 是一个特殊字符。您需要使用 Matcher.quoteReplacement(mr.group().substring(1)):

String output = Pattern.compile("(\\\\+\")")
           .matcher(text)
           .replaceAll(mr -> Matcher.quoteReplacement(mr.group().substring(1)));

参见Java demo

这里不需要使用 lambda,可以使用

String text = "test\\\\\"escape\\\"test\\ that";
String output = text.replaceAll("\\\\(\\\\*\")","$1");
System.out.println(output);
// => test\"escape"test\ that

参见 Java demoregex demo

\\(\\*") 正则表达式匹配一个 \,然后将零个或多个反斜杠捕获到后面带有 " 的第 1 组,替换为第 1 组的值。