Я бы сделал это так:
:%s/\v(foo|bar)/\={'foo':'bar','bar':'foo'}[submatch(0)]/g
Но это слишком много печатать, поэтому я бы сделал это:
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
Но для этого все равно требуется дважды набрать foo
и bar
, поэтому я бы сделал что-то вроде этого:
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'})
Если одно из ваших слов содержит /
, вы должны передать разделитель, который, как вы знаете, ни одно из ваших слов не содержит, например,
:call SwapWords({'foo/bar':'foo/baz'}, '@')
Преимущество заключается в возможности обмена несколькими парами слов одновременно.
:call SwapWords({'foo':'bar', 'baz':'quux'})