What is the easiest way to replace all occurrences of string_a
with string_b
while at the same time changing anything that was already string_b
into string_a
? My current method is as follows:
:s/string_a/string_c/g :s/string_b/string_a/g :s/string_c/string_b/g
Although this works, it requires extra typing and seems inefficient. Does anybody know of a better way to do this?
Change and repeat Search for text using / or for a word using * . In normal mode, type cgn (change the next search hit) then immediately type the replacement. Press Esc to finish. From normal mode, search for the next occurrence that you want to replace ( n ) and press . to repeat the last change.
The % is a shortcut that tells vi to search all lines of the file for search_string and change it to replacement_string . The global ( g ) flag at the end of the command tells vi to continue searching for other occurrences of search_string . To confirm each replacement, add the confirm ( c ) flag after the global flag.
Basic Find and Replace In Vim, you can find and replace text using the :substitute ( :s ) command. To run commands in Vim, you must be in normal mode, the default mode when starting the editor. To go back to normal mode from any other mode, just press the 'Esc' key.
I'd do it like this:
:%s/\v(foo|bar)/\={'foo':'bar','bar':'foo'}[submatch(0)]/g
But that's too much typing, so I'd do this:
function! Mirror(dict) for [key, value] in items(a:dict) let a:dict[value] = key endfor return a:dict endfunction function! S(number) return submatch(a:number) endfunction :%s/\v(foo|bar)/\=Mirror({'foo':'bar'})[S(0)]/g
But that still requires typing foo
and bar
twice, so I'd do something like this:
function! SwapWords(dict, ...) let words = keys(a:dict) + values(a:dict) let words = map(words, 'escape(v:val, "|")') if(a:0 == 1) let delimiter = a:1 else let delimiter = '/' endif let pattern = '\v(' . join(words, '|') . ')' exe '%s' . delimiter . pattern . delimiter \ . '\=' . string(Mirror(a:dict)) . '[S(0)]' \ . delimiter . 'g' endfunction :call SwapWords({'foo':'bar'})
If one of your words contains a /
, you have to pass in a delimiter which you know none of your words contains, .e.g
:call SwapWords({'foo/bar':'foo/baz'}, '@')
This also has the benefit of being able to swap multiple pairs of words at once.
:call SwapWords({'foo':'bar', 'baz':'quux'})
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With