In Vim how can I search and replace every other match?

后端 未结 7 1265
Happy的楠姐
Happy的楠姐 2020-12-23 23:41

Say I have the following file


    
    


    

        
7条回答
  •  挽巷
    挽巷 (楼主)
    2020-12-24 00:03

    Here's a custom command that should do the trick. It uses a replace expression to count the replacements done, and uses a passed additional argument to decide whether a replacement should be done. (This allows more complex arrangements than every second one.) Your example would then be a simple:

    :%SubstituteSelected/\/&1/ yn
    

    Here's the (unfortunately quite long) implementation:

    ":[range]SubstituteSelected/{pattern}/{string}/[flags] {answers}
    "           Replace matches of {pattern} in the current line /
    "           [range] with {string}, determining whether a particular
    "           match should be replaced on the sequence of "y" or "n"
    "           in {answers}. I.e. with "ynn", the first match is
    "           replaced, the second and third are not, the fourth is
    "           again replaced, ...
    "           Handles & and \0, \1 .. \9 in {string}.
    function! CountedReplace()
        let l:index = s:SubstituteSelected.count % len(s:SubstituteSelected.answers)
        let s:SubstituteSelected.count += 1
    
        if s:SubstituteSelected.answers[l:index] ==# 'y'
            if s:SubstituteSelected.replacement =~# '^\\='
                " Handle sub-replace-special.
                return eval(s:SubstituteSelected.replacement[2:])
            else
                " Handle & and \0, \1 .. \9 (but not \u, \U, \n, etc.)
                let l:replacement = s:SubstituteSelected.replacement
                for l:submatch in range(0, 9)
                    let l:replacement = substitute(l:replacement,
                    \   '\%(\%(^\|[^\\]\)\%(\\\\\)*\\\)\@SubstituteSelected(',', )
    

    Edit

    I've now published this (together with related commands) as the PatternsOnText plugin.

提交回复
热议问题