Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

vim regex for replacing spaces within quotes

Tags:

regex

vim

I have text in the follwing format:

ERR_OUT_OF_MEM, "ERR OUT OF MEM"
ERR_SOMETHING_BAD, "ERR SOMETHING BAD"

I want to replace all spaces in the text which are within quotes with underscores:

 ERR_OUT_OF_MEM, "ERR_OUT_OF_MEM"
 ERR_SOMETHING_BAD, "ERR_SOMETHING_BAD"

The best regex I could come up with is:

\("\w\+\)\@<= 

(there's a space at the end of that)

but this only finds the first space in each quoted string, and I would need to repeat this multiple times to get the desired effect.

Any way to do it in one shot?

Thanks!

like image 645
vicky.dev Avatar asked Jun 04 '10 13:06

vicky.dev


2 Answers

There is certainly a 0-length pattern that works in one pass, but as I never have much success using them, I prefer this kind of approach:

:%s/\%("[^"]*"\)*\("[^"]*"\)/\=substitute(submatch(1), ' ', '_', 'g')/g

Note: double-quotes are kept grouped 2 by 2 in order to not transform

foo bar "foo bar" "foo barr"

into

foo bar "foo_bar"_"foo_barr"

EDIT: as rampion pointed out, the following is more than enough:

%s/"[^"]*"/\=substitute(submatch(0), ' ', '_', 'g')/g
like image 52
Luc Hermitte Avatar answered Nov 07 '22 16:11

Luc Hermitte


This isn't a general-purpose solution, since it will match any space that appears anywhere after a double quote on a line, but it should work for strings in the format you've specified:

s/\v(\".*)@<= /_/g

I've used the \v (verymagic) token because I think it makes the regex a little more readable, and I included the whole substitution command, since the 'g' at the end is important.

For those following along at home, this regex first sets 'verymagic' mode with \v. Then it defines the token (\".*) which roughly means "a double quote and then anything else" and uses the lookbehind assertion @<= to say "only match things following that last token" - in other words, only match things that come somewhere after a double quote. Finally, there's a space, which is what actually gets matched, and the substitution term is an underscore, which is what we want to replace it with, and the g says "substitute all matching terms" so we don't just get the first match found.

like image 31
John Hyland Avatar answered Nov 07 '22 16:11

John Hyland