如何正确转义和取消转义包含换行符文字的多行字符串?

3
我正在开发一款Visual Studio Code扩展。该扩展应该对当前编辑器窗口中选定的文本进行操作,并将其发送到外部命令(在我的情况下是lein-cljfmt,但我认为这与我的问题无关)。当外部命令处理完文本后,我想用从命令行工具返回的结果替换当前编辑器选择器。
在发送字符串之前,我会像这样对其进行转义:
contents
    .replace(/\\/g, '\\\\')
    .replace(/"/g, '\\"')
    .replace(/\n/g, '\\n');

结果没有被转义,如下所示:
contents
    .replace(/\\n/g, '\n')
    .replace(/\\"/g, '"')
    .replace(/\\\\/g, '\\');

这在除了一种情况以外都能正常工作:当正在处理的选择包含一个包含换行符文本的字符串字面量时,反转义将会把其转换为换行符,从而在编辑器中导致程序出错。

以下是一个会使我的转义出错的代码片段示例:

(defn join
  [a b]
  (str a "\n" b)) 

我尝试了一些正则表达式黑魔法,例如
.replace(/(?!\B"[^"]*)\\n(?![^"]*"\B)/g, '\n')

到目前为止,我还没有找到一种没有边缘情况的解决方案。我是否遗漏了某种方法?我还想知道是否有VSCode扩展API可以处理这个问题,因为它对我来说似乎是一个常见的情况。


请使用反引号而不是单引号或双引号将字符串括起来。 - smoore4
1个回答

5
我认为这可能是您需要的内容:

function slashEscape(contents) {
    return contents
        .replace(/\\/g, '\\\\')
        .replace(/"/g, '\\"')
        .replace(/\n/g, '\\n');
}

var replacements = {'\\\\': '\\', '\\n': '\n', '\\"': '"'};

function slashUnescape(contents) {
    return contents.replace(/\\(\\|n|")/g, function(replace) {
        return replacements[replace];
    });
}

var tests = [
    '\\', '\\\\', '\n', '\\n', '\\\n', '\\\\n',
    '\\\\\n', '\\\\\\n', '\\"\\\\n', '\n\n',
    '\n\n\n', '\\n\n', '\n\\n', '\\n\\n',
    '\\\n\\n\nn\n\\n\\\n\\\\n', '"', '\\"', '\\\\"'
];

tests.forEach(function(str) {
    var out = slashUnescape(slashEscape(str));
    
    // assert that what goes in is what comes out
    console.log(str === out, '[' + str + ']', '[' + out + ']');
});

尝试在三个阶段内对字符串进行反转义真的很棘手,因为\n取决于它前面有多少斜杠而有不同的含义。 在您的示例中,原始字符串\n(斜杠 n)被编码为\\n(斜杠斜杠 n),然后当您对其进行解码时,最后两个字符与第一个RegExp的第一个字符相匹配,但您希望前两个字符与第三个RegExp相匹配。 您必须计算斜杠数量以确保准确性。一次完成所有操作可以同时解码这些前导斜杠,从而规避了该问题。

感谢您的回答。但我想再等一会儿,看是否有人知道是否可以使用VSCode API来完成此操作。 - m90

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接