Let's say I have string "The quick brown fox jumps over the lazy dog" can I change this to "The slow brown fox jumps over the energetic dog" with one regular expression? Currently, I use two sets of regular expressions for this situation. (In this case, I use s/quick/slow/
followed by s/lazy/energetic/
.)
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.
Vim has several regex modes, one of which is very magic that's very similar to traditional regex. Just put \v in the front and you won't have to escape as much.
You can do this in vim using a Dictionary:
:%s/quick\|lazy/\={'quick':'slow','lazy':'energetic'}[submatch(0)]/g
This will change the following text:
The quick brown fox ran quickly next to the lazy brook.
into:
The slow brown fox ran slowly next to the energetic brook.
To see how this works, see :help sub-replace-expression
and :help Dictionary
. In short,
\=
lets you substitute in the result of a vim expression. {'quick':'slow', 'lazy':'energetic'}
is a vim dictionary (like a hash in perl or ruby, or an object in javascript) that uses []
for lookups. submatch(0)
is the matched string This can come in handy when refactoring code - say you want to exchange the variable names for foo
, bar
, and baz
changing
foo
→ bar
bar
→ baz
baz
→ foo
Using a sequence of %s///
commands would be tricky, unless you used temporary variable names - but you'd have to make sure those weren't hitting anything else. Instead, you can use a Dictionary to do it in one pass:
:%s/\<\%(foo\|bar\|baz\)\>/\={'foo':'bar','bar':'baz','baz':'foo'}[submatch(0)]/g
Which changes this code
int foo = 0; float bar = pow(2.0, (float) foo); char baz[256] = {}; sprintf(baz,"2^%d = %f\n", foo, bar);
into:
int bar = 0; float baz = pow(2.0, (float) bar); char foo[256] = {}; sprintf(foo,"2^%d = %f\n", bar, baz);
If you find yourself doing this a lot, you may want to add the following to your ~/.vimrc
:
" Refactor the given lines using a dictionary " replacing all occurences of each key in the dictionary with its value function! Refactor(dict) range execute a:firstline . ',' . a:lastline . 's/\C\<\%(' . join(keys(a:dict),'\|'). '\)\>/\='.string(a:dict).'[submatch(0)]/ge' endfunction command! -range=% -nargs=1 Refactor :<line1>,<line2>call Refactor(<args>)
This lets you use the :Refactor {'frog':'duck', 'duck':'frog'}
command, and is slightly less repetitive than creating the regex for the dict manually.
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