Самый простой способ поменять местами две строки в Vim? - PullRequest
37 голосов
/ 26 августа 2010

Какой самый простой способ заменить все вхождения string_a на string_b и в то же время заменить все, что уже было string_b на string_a? Мой текущий метод заключается в следующем:

:s/string_a/string_c/g  
:s/string_b/string_a/g  
:s/string_c/string_b/g  

Хотя это работает, оно требует дополнительной печати и кажется неэффективным. Кто-нибудь знает лучший способ сделать это?

Ответы [ 5 ]

25 голосов
/ 27 августа 2010

Я бы сделал это так:

:%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'})
12 голосов
/ 10 июля 2013

Вы можете легко сделать это с помощью Abolish плагина

Тима Папы
:%S/{transmit,receive}/{receive,transmit}
3 голосов
/ 19 июня 2016

Вот как я поменяю местами два слова skip & limit.

%s/skip/xxxxx/g|%s/limit/skip/g|%s/xxxxx/limit/g

Уверен, кто-то может превратить ее в более короткую команду, которая принимает два аргумента.

2 голосов
/ 24 декабря 2013

Плагин swapstrings предоставляет удобную команду для этого:

:SwapStrings string_a string_b
1 голос
/ 26 августа 2010

Вы можете сделать это с помощью одной команды, как показано в моем коде ниже:

:%s/\<\(string_a\|string_b\)\>/\=strpart("string_bstring_a", 8 * ("string_b" == submatch(0)), 8)/g

Обновление: редактор здесь в stackoverflow сводит меня с ума, потому что он продолжает удалять обратные слеши...

...