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

时间:2010-08-26 19:01:46

标签: vim scripting vi

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 个答案:

答案 0 :(得分:25)

我会这样做:

:%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

但仍然需要输入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'})

如果您的某个单词包含/,则必须传入一个您知道没有任何单词包含的分隔符,.e.g

:call SwapWords({'foo/bar':'foo/baz'}, '@')

这样做的好处是可以同时交换多对单词。

:call SwapWords({'foo':'bar', 'baz':'quux'})

答案 1 :(得分:12)

您可以使用Tim Pope的Abolish插件轻松完成此操作

:%S/{transmit,receive}/{receive,transmit}

答案 2 :(得分:3)

以下是我如何交换两个单词skip& limit

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

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

答案 3 :(得分:2)

swapstrings plugin为此提供了一个方便的命令:

:SwapStrings string_a string_b

答案 4 :(得分:1)

您可以使用单个命令执行此操作,如下面的代码所示:

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

更新: stackoverflow中的编辑器让我发疯,因为它一直在消除反击......