【问题标题】:Search & replace using quickfix list in Vim在 Vim 中使用 quickfix 列表搜索和替换
【发布时间】:2011-08-06 20:54:18
【问题描述】:

到目前为止,我一直使用 EasyGrep 来替换多个文件中的文本。不幸的是,当项目变得更大时,它会很慢。似乎非常快的一件事是 fugitive.vim 的 Ggrep,它只搜索我的版本控制文件。所有结果也存储在 quickfix 列表中。

如何使用 Ggrep 的结果对所有找到的文件进行简单替换?是否有可能在快速修复列表中的所有文件上使用%s/foo/bar/cg,或者有更好的方法吗?

【问题讨论】:

    标签: search vim replace


    【解决方案1】:

    更新: Vim 现在有cdo,见Sid's answer

    原答案:

    Vim 有bufdowindotabdoargdo,可以让你在参数列表中所有打开的缓冲区、窗口或文件中执行相同的命令。我们真正需要的是像quickfixdo 这样的东西,它会在quickfix 列表中的每个文件上调用一个命令。遗憾的是,Vim 缺少该功能,但 here's a solution by Al 提供了一个自制的解决方案。使用它,可以运行:

    :QFDo %s/foo/bar/gc
    

    这将在 quickfix 列表中的所有文件上运行 foo/bar 替换。

    bufdowindotabdoargdo 命令有一些共同的行为。例如,如果当前文件不能被放弃,那么所有这些命令都会失败。我不确定上面引用的QFDo 命令是否遵循相同的约定。

    我已经修改了Al's solution 来创建一个名为Qargs 的命令。运行此命令会使用 quickfix 列表中列出的所有文件填充参数列表:

    command! -nargs=0 -bar Qargs execute 'args ' . QuickfixFilenames()
    function! QuickfixFilenames()
      " Building a hash ensures we get each buffer only once
      let buffer_numbers = {}
      for quickfix_item in getqflist()
        let buffer_numbers[quickfix_item['bufnr']] = bufname(quickfix_item['bufnr'])
      endfor
      return join(values(buffer_numbers))
    endfunction
    

    使用它,您可以按照以下步骤进行项目范围的搜索和替换:

    :Ggrep findme
    :Qargs
    :argdo %s/findme/replacement/gc
    :argdo update
    

    编辑:(向 Peter Rincker 致敬)

    或者您可以将最后 3 个命令合并到一行中:

    :Ggrep findme
    :Qargs | argdo %s/findme/replacement/gc | update
    

    【讨论】:

    • 我相信你应该在你的Qargs 命令中使用-nargs=0-bar
    • 使用argsargdo 是个好主意!我认为将Qargsargdo 命令合二为一会更好(也更方便):command! -nargs=1 -complete=command -bang Qargdo exe 'args '.QuickfixFilenames() | argdo<bang> <args>
    • 我创建了一个简单的插件来包装:Qargs 命令:github.com/nelstrom/vim-qargs
    • @ib。谢谢你(当然还有@nelstrom)。分叉 @nelstrom 的插件以添加您的 Qargdo,但作为 Qdo 以减少命令完成冲突:github.com/henrik/vim-qargs
    • 一个补丁 was submitted 将 :cdo 和 :ldo 命令添加到 Vim。
    【解决方案2】:

    cdo 命令现已添加! grep 后,您可以使用cdo 对您的快速修复列表中的每个术语执行给定的命令:

    cdo %s/<search term>/<replace term>/cg

    (查看git commitvim developers google group discussion,了解有关cdo 的更多信息以及添加它的动机。)

    【讨论】:

    • 我认为 replace 命令不应包含 % 以防止替换所选列表之外的行。如果替换不是幂等的,也可能导致意外结果。
    • 使用cdo 还为更灵活的操作提供了惊人的选项。例如cdo norm capMy new paragraph 这个例子在每次出现搜索词时运行normal,将搜索词周围的整个段落更改为“我的新段落”。惊人的强大。
    • 我还需要将上面的内容传递给“update”命令,否则 vim 不想移动到下一个文件,因为缓冲区已被编辑但未保存。命令:cdo %s/<search term>/<replace term>/gc | update
    【解决方案3】:

    nelstrom 的回答相当全面,反映了他对 vimdom 的杰出贡献。它也有点超出了这里的严格要求;可以省略快速修复步骤,以便使用 shell 命令的结果填充 args:

    :args `git grep -l findme`
    :argdo %s/findme/replacement/gc
    :argdo update
    

    应该是你所需要的。

    编辑:正如 Domon 所说, :set hidden 如果尚未设置,则必须先完成!

    【讨论】:

    • +1 务实的解决方案。基于此,您还可以在启动 vim 时填充 arglist:vim `git grep -l findme`
    • 这对我有用。但是,我必须在 :argo ... 之前 :set hidden 否则 Vim 会因为未保存的更改而出错。
    【解决方案4】:

    外部grep

    (使用 grepprg、grepformat 就像在 makeprg/errorformat 中一样;如果 grepprg=='internal' 这与 internal grep 相同)

    :grep fopen *.c
    :copen
    :cnext
    

    内部grep

    :vimgrep /\<myVimregexp\>/ **/*.c
    :copen
    :cnext
    

    等等

    位置列表内部 grep

    :lvimgrep /\<myVimregexp\>/ **/*.c
    :lopen
    :lnext
    

    等等

    奖励:为加载的缓冲区执行外部 grep:

    :silent bufdo grepadd fstream %
    :copen
    :cnext
    

    等等

    所有参数的外部参数:

    :silent argdo grepadd fstream %
    :copen
    :cnext
    

    【讨论】:

    • 不确定您要通过这些示例指出什么。我知道如何使用 grep 和 vimgrep。我不明白这个答案如何适合这个问题。
    • (a) 向您展示一些减少 vim 中 grep 范围的方法 (b) 向您展示如何为外部 grep 做这些事情。如果有点无聊,我很抱歉,但它对我有用:)
    【解决方案5】:

    使用quickfix-reflector.vim,您可以在快速修复窗口中编辑您的搜索结果。然后write 命令会将更改保存到您的文件中。

    :copen
    :%s/foo/bar/cg
    :write
    

    【讨论】:

      【解决方案6】:

      有一个补丁可以将cdo(Quickfix do)命令添加到vim,但是还没有拉出来(截至2015-03-25):

      https://groups.google.com/forum/#!topic/vim_dev/dfyt-G6SMec

      你可能想自己给 vim 打补丁来获得这个补丁:

      brew install hg # install mercurial, e.g. with homebrew
      hg clone https://vim.googlecode.com/hg/ vim
      cd vim
      # copy/download patch to . folder
      patch -b -p1 < cdo.diff
      ./configure
      make && make install
      

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2021-09-06
        • 2011-05-04
        • 2011-11-09
        • 1970-01-01
        • 2011-06-15
        • 1970-01-01
        相关资源
        最近更新 更多