在Vim中交换两个字符串的最简单方法?

btw*_*btw 37 vi vim scripting

什么是更换所有出现的最简单的方法string_astring_b,而在同一时间改变任何东西,已经string_bstring_a?我目前的方法如下:

:s/string_a/string_c/g  
:s/string_b/string_a/g  
:s/string_c/string_b/g  
Run Code Online (Sandbox Code Playgroud)

虽然这有效,但它需要额外的打字并且效率低下.有人知道更好的方法吗?

Bri*_*per 26

我这样做:

:%s/\v(foo|bar)/\={'foo':'bar','bar':'foo'}[submatch(0)]/g
Run Code Online (Sandbox Code Playgroud)

但那打字太多了,所以我会这样做:

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
Run Code Online (Sandbox Code Playgroud)

但是,仍然需要打字foobar的两倍,因此我会做这样的事情:

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'})
Run Code Online (Sandbox Code Playgroud)

如果你的一个单词包含a /,你必须传入一个你知道没有任何单词包含的分隔符,例如

:call SwapWords({'foo/bar':'foo/baz'}, '@')
Run Code Online (Sandbox Code Playgroud)

这还具有能够一次交换多对单词的好处.

:call SwapWords({'foo':'bar', 'baz':'quux'})
Run Code Online (Sandbox Code Playgroud)


Pet*_*ker 12

你可以使用Tim Pope的Abolish插件轻松完成

:%S/{transmit,receive}/{receive,transmit}
Run Code Online (Sandbox Code Playgroud)

  • @JanNetherdrake如果要使用整个单词,请使用Subvert的`w`标志。`:%S / {test,foo} / {foo,test} / gw`。有关更多信息,请参见`:h abolish-search`。 (2认同)

ptg*_*amr 5

这是我交换两个单词skip&的方法limit

%s/skip/xxxxx/g | %s/limit/skip/g | %s/xxxxx/limit/g
Run Code Online (Sandbox Code Playgroud)

很确定有人可以将它变成一个更短的命令,它接受两个参数。