我有一些文字,其中一些行包含字符串中正确转义的双引号,而某些行则不包含 如下所示:
bla1 "aaa"bbb"ccc" bla1
bla2 "aaa\"bbb\"ccc" bla2
替换后的结果应为
bla1 "aaa\"bbb\"ccc" bla1
bla2 "aaa\"bbb\"ccc" bla2
但不是:
bla1 "aaa\"bbb\"ccc" bla1
bla2 "aaa\\"bbb\\"ccc" bla2
换句话说,它应该在没有转义的行中转义双引号 并且不要触摸已经正确转义的行
到目前为止,我用这个
获得了第二个结果%s:\(\s".\+\)\(".\+\)\(".\+"\s\):\1\\\2\\\3:g
然后我尝试了一个负面的观察,告诉引擎不匹配 如果在引号
之前有反斜杠(?<!\) which in vim should be something like @<!\
%s:\(\s".\+\)\@<!\\\(".\+\)@<!\\\(".\+"\s\):\1\\\2\\\3:g
但我觉得我有点失落。
注意:
每行只有一个这样的字符串
该字符串用双引号括起来,里面可以包含双引号 - 只有一个内部应该被转义
答案 0 :(得分:3)
由于您说每行只有一个字符串,您可以链接替换命令以获得所需的结果。 (这也可以使命令的所有部分更容易正则表达式)
:%s/"\zs.*\ze"/\=substitute(submatch(0), '\\\@<!"', '\\"', 'g')
说明:
:%s/"\zs.*\ze"
匹配第一个和最后一个引号之间的所有内容。我们使用贪婪的.*
来做到这一点。 \zs
标记了比赛的开始,\ze
标志着比赛的结束。之后我们可以通过将\=
添加到替换的开头来将匹配传递给第二个替换命令。这意味着它之后的表达式的结果将是替换字符串。
substitute(submatch(0), '\\\@<!"', '\\"', 'g')
submatch(0)
是引号之间的所有内容。然后,我们将所有没有斜杠的引号(\\\@<!"
)替换为\"
。
在:h sub-replace-expression
,:h /\zs
和:h /\ze
示例输入:
bla1 "aaa"bbb"ccc" bla1
bla2 "aaa\"bbb\"ccc" bla2
bla\bla3 "aaa"bbb"ccc" bla3
blabla4 "aaa"bbb" "BBB"ccc" bla4
bla\bla5 "aaa"bbb" "BBB"ccc" bla5
bla\bla5 "aaa"bbb""BBB"ccc" bla5
示例输出:
bla1 "aaa\"bbb\"ccc" bla1
bla2 "aaa\"bbb\"ccc" bla2
bla\bla3 "aaa\"bbb\"ccc" bla3
blabla4 "aaa\"bbb\" \"BBB\"ccc" bla4
bla\bla5 "aaa\"bbb\" \"BBB\"ccc" bla5
bla\bla5 "aaa\"bbb\"\"BBB\"ccc" bla5
答案 1 :(得分:1)
你可以在你已经写过的命令之一上加上反向全局。现在它只适用于不包含已转义的引号的行:
:v/\\"/s:\(\s".\+\)\(".\+\)\(".\+"\s\):\1\\\2\\\3:g
答案 2 :(得分:0)
:%s/\([^ \\]\)"\([^ ]\)/\1\\"\2/g
这会发现引号前面没有斜杠或空格,后面没有空格。
答案 3 :(得分:0)
这可能有效:
%s/\([^\\]\)\("\)/\1\\\2/g