【问题标题】:How do I properly escape and unescape a multiline string that contains newline literals?如何正确转义和取消转义包含换行文字的多行字符串?
【发布时间】:2018-02-25 10:10:48
【问题描述】:

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

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

contents
    .replace(/\\/g, '\\\\')
    .replace(/"/g, '\\"')
    .replace(/\n/g, '\\n');

未转义的结果如下:

contents
    .replace(/\\n/g, '\n')
    .replace(/\\"/g, '"')
    .replace(/\\\\/g, '\\');

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

这是一个打破我转义的 sn-p 示例:

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

我尝试了相当多的正则表达式黑魔法

.replace(/(?!\B"[^"]*)\\n(?![^"]*"\B)/g, '\n')

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

【问题讨论】:

  • 用反引号将字符串括起来,而不是单引号或双引号

标签: javascript regex escaping visual-studio-code vscode-extensions


【解决方案1】:

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

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 + ']');
});

尝试在 3 个阶段中对字符串进行转义非常棘手,因为 \n 具有不同的含义,具体取决于它之前有多少个斜杠。在您的示例中,\n (slash n) 的原始字符串被编码为 \\n (slash slash n),然后当您对其进行解码时,最后两个字符与您的 RegExps 中的第一个字符匹配,而您想要的是前两个字符匹配第三个 RegExp 的字符。你必须计算斜线才能确定。通过同时解码前导斜杠,一次性完成所有操作可以避免该问题。

【讨论】:

  • 感谢您的回答,我想暂时保持开放状态,因为也许有人会知道这是否可以使用 VSCode API 来完成。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2020-09-28
  • 2012-02-27
  • 2011-05-14
  • 2021-05-18
  • 1970-01-01
  • 2019-09-19
相关资源
最近更新 更多