Substitution pattern to escape quotes in vim
escaping, regex, vim
Solution
Since you said there is only 1 string on each line, you can chain substitute commands to get the result that you want. (This also leads to easier regexes in all parts of the command)
:%s/"\zs.*\ze"/\=substitute(submatch(0), '\\\@<!"', '\\"', 'g')
Explanation:
- `:%s/"\zs.*\ze"` matches everything on the line between the first and the last quote. We use the greedy `.*` to do this. `\zs` marks the start of the match and `\ze` marks the end of the match.
After that we can pass the match to a second substitute command by adding `\=` to the start of the replacement. This means that the result of the expression after it will be the replacement string.
substitute(submatch(0), '\\\@<!"', '\\"', 'g')
`submatch(0)` is everything between the quotes. We then replace all quotes that don't have a slash before it (`\\\@<!"`) with a `\"`.
Take a loot at `:h sub-replace-expression`, `:h /\zs` and `:h /\ze`
Example Input:
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
Example Output:
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
Problem
I have text with some lines contains properly escaped double quotes in strings and some not like below: ``` bla1 "aaa"bbb"ccc" bla1 bla2 "aaa\"bbb\"ccc" bla2 ``` The results after substitution should be ``` bla1 "aaa\"bbb\"ccc" bla1 bla2 "aaa\"bbb\"ccc" bla2 ``` but not: ``` bla1 "aaa\"bbb\"ccc" bla1 bla2 "aaa\\"bbb\\"ccc" bla2 ``` In other words it should escape the double quotes in lines where they are not escaped and do not touch lines which are already properly escaped So far I got the second result with this ``` %s:\(\s".\+\)\(".\+\)\(".\+"\s\):\1\\\2\\\3:g ``` Then I've tried a negative lookbehind to tell the engine to not match if there is a backslash before the quotes ``` (?<!\) which in vim should be something like @<!\ %s:\(\s".\+\)\@<!\\\(".\+\)@<!\\\(".\+"\s\):\1\\\2\\\3:g ``` But I think I've got a little lost. Note: There is only one such string per line The string is enclosed in double quotes and can contain double quotes inside - only this inside one should be escaped