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

m90*_*m90 3 javascript regex escaping visual-studio-code vscode-extensions

我正在开发 Visual Studio Code 扩展。该扩展应该作用于编辑器窗口中当前选择的文本并将其发送到外部命令(lein-cljfmt在我的情况下,但我认为这与我的问题无关)。当外部命令处理完文本后,我想用命令行工具返回的结果替换当前编辑器选择器。

在发送字符串之前,我像这样转义它:

contents
    .replace(/\\/g, '\\\\')
    .replace(/"/g, '\\"')
    .replace(/\n/g, '\\n');
Run Code Online (Sandbox Code Playgroud)

未转义的结果如下:

contents
    .replace(/\\n/g, '\n')
    .replace(/\\"/g, '"')
    .replace(/\\\\/g, '\\');
Run Code Online (Sandbox Code Playgroud)

除了一种情况之外,这在所有情况下都有效:当正在处理的选择包含包含换行符文字的字符串文字时,取消转义会将其转换为换行符,从而破坏编辑器中的代码。

这是打破我的转义的片段示例:

(defn join
  [a b]
  (str a "\n" b)) 
Run Code Online (Sandbox Code Playgroud)

我尝试了一些正则表达式黑魔法,比如

.replace(/(?!\B"[^"]*)\\n(?![^"]*"\B)/g, '\n')
Run Code Online (Sandbox Code Playgroud)

到目前为止,但找不到没有边缘情况的解决方案。有没有一种方法可以做到我所缺少的?我还想知道是否有一个 VSCode 扩展 API 可以处理这个问题,因为这对我来说似乎是一个常见的场景。

ski*_*tle 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 + ']');
});
Run Code Online (Sandbox Code Playgroud)

尝试分 3 个阶段对字符串进行转义确实很棘手,因为\n根据其前面有多少个斜杠,其含义也不同。在您的示例中,(斜杠 n) 的原始字符串\n被编码为\\n(斜杠斜杠 n),然后当您对其进行解码时,最后两个字符与您的正则表达式的第一个匹配,而您想要的是前两个字符与第三个正则表达式匹配。你必须数一下斜线才能确定。一次性完成这一切可以通过同时解码那些前导斜线来避免这个问题。