如何从VIM中的字符串列表中替换?
发布时间:2020-12-15 18:58:20 所属栏目:安全 来源:网络整理
导读:我是一个vim用户,我希望能够在替换时循环一系列子串.我如何使用一些vim魔法来从这样的一组行: AfooBfooCfooDfoo 至 AbarBbarCbazDbaz ? 我想从头开始搜索我的文件,以便下一次出现foo,并用bar替换前两个实例,用baz替换后两个实例.使用for循环是最好的选择吗
我是一个vim用户,我希望能够在替换时循环一系列子串.我如何使用一些vim魔法来从这样的一组行:
Afoo Bfoo Cfoo Dfoo 至 Abar Bbar Cbaz Dbaz ? 我想从头开始搜索我的文件,以便下一次出现foo,并用bar替换前两个实例,用baz替换后两个实例.使用for循环是最好的选择吗?如果是这样,那么如何在替换命令中使用循环变量?
我会使用一个具有状态的函数,并从%s调用此函数.就像是:
" untested code function! InitRotateSubst() let s:rs_idx = 0 endfunction function! RotateSubst(list) let res = a:list[s:rs_idx] let s:rs_idx += 1 if s:rs_idx == len(a:list) let s:rs_idx = 0 endif return res endfunction 并使用它们: :call InitRotateSubst() :%s/foo/=RotateSubst(['bar','bar','baz','baz'])/ 如果您愿意,可以将对这两个命令的调用封装到单个命令中. 编辑:这是一个集成为命令的版本: >根据需要接受尽可能多的替换,所有替换都需要用分隔符分隔; 这是命令定义: :command! -bang -nargs=1 -range RotateSubstitute <line1>,<line2>call s:RotateSubstitute("<bang>",<f-args>) function! s:RotateSubstitute(bang,repl_arg) range let do_loop = a:bang != "!" " echom "do_loop=".do_loop." -> ".a:bang " reset internal state let s:rs_idx = 0 " obtain the separator character let sep = a:repl_arg[0] " obtain all fields in the initial command let fields = split(a:repl_arg,sep) " prepare all the backreferences let replacements = fields[1:] let max_back_ref = 0 for r in replacements let s = substitute(r,'.{-}(d+)','1','g') " echo "s->".s let ls = split(s,'') for d in ls let br = matchstr(d,'d+') " echo '##'.(br+0).'##'.type(0) ." ~~ " . type(br+0) if !empty(br) && (0+br) > max_back_ref let max_back_ref = br endif endfor endfor " echo "max back-ref=".max_back_ref let sm = '' for i in range(0,max_back_ref) let sm .= ','. 'submatch('.i.')' " call add(sm,) endfor " build the action to execute let action = '=s:DoRotateSubst('.do_loop.',' . string(replacements) . sm .')' " prepare the :substitute command let args = [fields[0],action ] let cmd = a:firstline . ',' . a:lastline . 's' . sep . join(args,sep) " echom cmd " and run it exe cmd endfunction function! s:DoRotateSubst(do_loop,list,replaced,...) " echom string(a:000) if ! a:do_loop && s:rs_idx == len(a:list) return a:replaced else let res0 = a:list[s:rs_idx] let s:rs_idx += 1 if a:do_loop && s:rs_idx == len(a:list) let s:rs_idx = 0 endif let res = '' while strlen(res0) let ml = matchlist(res0,'(.{-})(d+)(.*)') let res .= ml[1] let ref = eval(substitute(ml[2],'(d+)','a:1','')) let res .= ref let res0 = ml[3] endwhile return res endif endfunction 可以这样使用: :%RotateSubstitute#foo#bar#bar#baz#baz# 甚至,考虑到初始文本: AfooZ BfooE CfooR DfooT 命令 %RotateSubstitute/(.)foo(.)/2bar1/1bar2/ 会产生: ZbarA BbarE RbarC DbarT (编辑:李大同) 【声明】本站内容均来自网络,其相关言论仅代表作者个人观点,不代表本站立场。若无意侵犯到您的权利,请及时与联系站长删除相关内容! |