Easiest way to swap occurrences of two strings in Vim?

后端 未结 5 1731
逝去的感伤
逝去的感伤 2020-12-04 15:39

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

相关标签:
5条回答
  • 2020-12-04 16:03

    The swapstrings plugin provides a handy command for this:

    :SwapStrings string_a string_b
    
    0 讨论(0)
  • 2020-12-04 16:04

    You can do this easily with Tim Pope's Abolish plugin

    :%S/{transmit,receive}/{receive,transmit}
    
    0 讨论(0)
  • 2020-12-04 16:15

    You can do it with a single command as shown in my code below:

    :%s/\<\(string_a\|string_b\)\>/\=strpart("string_bstring_a", 8 * ("string_b" == submatch(0)), 8)/g
    
    0 讨论(0)
  • 2020-12-04 16:26

    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'})
    
    0 讨论(0)
  • 2020-12-04 16:28

    Here is how I swap two words skip & limit:

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

    Pretty sure someone could turn it into a shorter command which accepts two arguments.

    0 讨论(0)
提交回复
热议问题