这是一个应该可以解决问题的自定义命令。它使用替换表达式来计算完成的替换,并使用传递的附加参数来决定是否应该进行替换。(这允许比每秒更复杂的安排。)您的示例将很简单:
:%SubstituteSelected/\<bar\>/&1/ yn
这是(不幸的是很长)实现:
":[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,
\ '\%(\%(^\|[^\\]\)\%(\\\\\)*\\\)\@<!' .
\ (l:submatch == 0 ?
\ '\%(&\|\\'.l:submatch.'\)' :
\ '\\' . l:submatch
\ ),
\ submatch(l:submatch), 'g'
\)
endfor
return l:replacement
endif
elseif s:SubstituteSelected.answers[l:index] ==# 'n'
return submatch(0)
else
throw 'ASSERT: Invalid answer: ' . string(s:SubstituteSelected.answers[l:index])
endif
endfunction
function! s:SubstituteSelected( range, arguments )
let l:matches = matchlist(a:arguments, '^\(\i\@!\S\)\(.*\)\%(\%(^\|[^\\]\)\%(\\\\\)*\\\)\@<!\1\(.*\)\%(\%(^\|[^\\]\)\%(\\\\\)*\\\)\@<!\1\(\S*\)\s\+\([yn]\+\)$')
if empty(l:matches)
echoerr 'Invalid arguments'
return
endif
let s:SubstituteSelected = {'count': 0}
let [l:separator, l:pattern, s:SubstituteSelected.replacement, l:flags, s:SubstituteSelected.answers] = l:matches[1:5]
execute printf('%ssubstitute %s%s%s\=CountedReplace()%s%s',
\ a:range, l:separator, l:pattern, l:separator, l:separator, l:flags
\)
endfunction
command! -bar -range -nargs=1 SubstituteSelected call <SID>SubstituteSelected('<line1>,<line2>', <q-args>)
编辑
我现在已将此(连同相关命令)作为PatternsOnText 插件发布。