使用Vim中的quickfix列表进行搜索和替换

Zar*_*doz 40 vim search replace

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

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

nel*_*rom 67

更新: Vim现在有cdo,见Sid的回答.

原答案:

Vim有bufdo,windo,tabdoargdo,让您在参数列表中的所有打开的缓冲区,窗口或文件执行相同的命令.我们真正需要的是quickfixdo,它会调用quickfix列表中每个文件的命令.遗憾的是,Vim缺乏这种功能,但这是Al 的解决方案,它提供了一个家庭解决方案.使用它,可以运行:

:QFDo %s/foo/bar/gc
Run Code Online (Sandbox Code Playgroud)

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

bufdo,windo,tabdoargdo命令有一些共同的行为.例如,如果无法放弃当前文件,则所有这些命令都将失败.我不确定QFDo上面引用的命令是否遵循相同的约定.

我已经改编了Al的解决方案来创建一个名为的命令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
Run Code Online (Sandbox Code Playgroud)

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

:Ggrep findme
:Qargs
:argdo %s/findme/replacement/gc
:argdo update
Run Code Online (Sandbox Code Playgroud)

编辑:( 给Peter Rincker提示帽子)

或者您可以在一行中将最后3个命令连接在一起:

:Ggrep findme
:Qargs | argdo %s/findme/replacement/gc | update
Run Code Online (Sandbox Code Playgroud)

  • @ib.谢谢你(当然还有@nelstrom).分叉@ nelstrom的插件添加你的`Qargdo`,但作为`Qdo`减少命令完成冲突:https://github.com/henrik/vim-qargs (9认同)
  • 已提交补丁[https://groups.google.com/forum/#!msg/vim_dev/dfyt-G6SMec/_6h8pDUpeZMJ]以将:cdo和:ldo命令添加到Vim. (4认同)
  • 我创建了一个简单的插件来包装`:Qargs`命令:https://github.com/nelstrom/vim-qargs (3认同)

Sid*_*Sid 37

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

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

(看看这个git提交和这个vim开发人员google小组讨论,了解更多信息cdo以及添加它的动机.)

  • 我认为替换命令不应包含“%”,以防止替换所选列表之外的行。如果替换不是幂等的,也可能会导致意外结果。 (3认同)
  • 我还需要将上面的内容通过管道传递给“更新”命令,否则 vim 不想移动到下一个文件,因为缓冲区已被编辑但未保存。命令 `:cdo %s/&lt;搜索词&gt;/&lt;替换词&gt;/gc | 更新` (2认同)

rho*_*div 14

nelstrom的答案非常全面,反映了他对vimdom的杰出贡献.它也超出了这里严格要求的范围; 可以省略quickfix步骤,以支持使用shell命令的结果填充args:

:args `git grep -l findme`
:argdo %s/findme/replacement/gc
:argdo update
Run Code Online (Sandbox Code Playgroud)

应该是你所需要的一切.

编辑:正如Domon所说,如果尚未设置隐藏必须先设置!

  • 这适合我.但是,我必须在`之前设置隐藏`:argo ...`或由于未保存的更改,Vim会出错. (2认同)

小智 5

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

:copen
:%s/foo/bar/cg
:write
Run Code Online (Sandbox Code Playgroud)