我正在寻找在Vim中对所有项目文件进行搜索和替换(确认)的最佳方法。 “项目文件”是指当前目录中的文件,其中一些文件不必打开。
执行此操作的一种方法是简单地打开当前目录中的所有文件:
:args ./**
然后对所有打开的文件进行搜索和替换:
:argdo %s/Search/Replace/gce
然而,当我这样做时,Vim的内存使用量从几十MB增加到超过2 GB,这对我不起作用。
我也安装了EasyGrep插件,但它几乎从不起作用 - 要么找不到所有出现的内容,要么直到按 Ctrl C才会挂起。到目前为止,我完成此任务的首选方法是ack-grep搜索词,使用它的quickfix窗口打开包含该词的任何文件,之前未打开,最后:bufdo %s/Search/Replace/gce
。
我正在寻找一个可以用于此的好的,有效的插件,或者一个命令/命令序列,它比我现在使用的那个更容易。
答案 0 :(得分:93)
这里的另一个重要选择就是不使用vim:
sed -i 's/pattern/replacement/' <files>
或者如果您有某种方法可以生成文件列表,可能是这样的:
find . -name *.cpp | xargs sed -i 's/pattern/replacement/'
grep -rl 'pattern1' | xargs sed -i 's/pattern2/replacement/'
等等!
答案 1 :(得分:48)
感谢最近添加的cdo
command,您现在可以使用已安装的grep
工具在两个简单的命令中执行此操作。无需额外的插件!:
1. :grep <search term>
2. :cdo %s/<search term>/<replace term>/gc
3. (If you want to save the changes in all files) :cdo update
(cdo
对quickfix列表中的每个术语执行给定命令,grep
命令填充该命令。)
(如果要在不确认每次搜索的情况下替换每个搜索词,请删除第二个命令末尾的c
。
答案 2 :(得分:33)
我决定使用ack和Perl来解决这个问题,以便利用更强大的完整Perl正则表达式而不是GNU子集。
ack -l 'pattern' | xargs perl -pi -E 's/pattern/replacement/g'
ack是一个很棒的命令行工具,它混合了grep
,find
和完整的Perl正则表达式(不仅仅是GNU子集)。它以纯Perl编写,速度快,具有语法高亮,适用于Windows,对程序员来说比传统的命令行工具更友好。使用sudo apt-get install ack-grep
在Ubuntu上安装它。
Xargs是一个旧的unix命令行工具。它从标准输入读取项目并执行指定的命令,然后执行标准输入读取的项目。因此,ack生成的文件列表基本上被附加到perl -pi -E 's/pattern/replacemnt/g'
命令的末尾。
Perl是一种编程语言。 -p选项使Perl在程序周围创建一个循环,该循环遍历文件名参数。 -i选项使Perl在适当的位置编辑文件。您可以修改它以创建备份。 -E选项使Perl执行指定为程序的一行代码。在我们的例子中,该程序只是一个Perl正则表达式替换。有关Perl命令行选项perldoc perlrun
的更多信息。有关Perl的更多信息,请参阅http://www.perl.org/。
答案 3 :(得分:26)
Greplace对我很有用。
github上还有一个pathogen ready version。
答案 4 :(得分:22)
也许这样做:
:noautocmd vim /Search/ **/*
:set hidden
:cfirst
qa
:%s//Replace/gce
:cnf
q
1000@a
:wa
说明:
:noautocmd vim /Search/ **/*
⇒查找(vim
是cwd所有子目录中所有文件的vimgrep
)模式的缩写,但没有触发autocmds(:noautocmd
),为了速度的缘故:set hidden
⇒允许修改缓冲区未显示在窗口中(可能在您的vimrc中):cfirst
⇒跳转到第一个搜索结果qa
⇒开始将宏记录到寄存器 a :%s//Replace/gce
⇒用/Search/
替换所有上次搜索模式(当时仍为Replace
):
g
标志)c
标志)e
标志):cnf
⇒跳转到vim
命令创建的列表中的下一个文件q
⇒停止录制宏1000@a
⇒播放1000次存储在寄存器中的宏:wa
⇒保存所有已修改的缓冲区*编辑* Vim 8路:
从Vim 8开始,有一种更好的方法,因为:cfdo
迭代了quickfix列表中的所有文件:
:noautocmd vim /Search/ **/*
:set hidden
:cfdo %s//Replace/gce
:wa
答案 5 :(得分:21)
:args
可以(在某些操作系统上 1 ))通过shell命令提供:args
的文件。
例如,如果您安装了 2 ,
:args `ack -l pattern`
将要求ack返回包含'pattern'的文件列表,并将它们放在参数列表中。
或者用普通的'grep'我猜它会是:
:args `grep -lr pattern .`
然后,您可以按照OP:
:argdo
:argdo %s/pattern/replacement/gce
:args
另请查看nelstrom's answer相关问题,该问题描述了从当前quickfix列表填充arglist的简单用户定义命令。这适用于许多命令和插件,其输出最终位于quickfix列表中(:vimgrep
,:Ack
3 ,:Ggrep
4 )。
然后可以使用以下命令执行项目范围搜索的序列:
:vimgrep /pattern/ **/*
:Qargs
:argdo %s/findme/replacement/gc
其中:Qargs
是对用户定义的命令的调用,该命令从quickfix列表填充arglist。
您还可以在ensuing discussion中找到简单插件中的链接,这些插件可将此工作流程缩减为2或3个命令。
答案 6 :(得分:7)
2016年的另一个选项far.vim插件:
答案 7 :(得分:5)
如果你不介意引入外部依赖,我已经制作了一个插件ctrlsf.vim(取决于ack或ag)来完成这项工作。
它可以格式化并显示来自ack / ag的搜索结果,并将结果缓冲区中的更改与磁盘上的实际文件同步。
也许以下演示解释更多
答案 8 :(得分:0)
基本上,我想在单个命令中更换,更重要的是在vim内部
基于answer by @Jefromi我创建了一个键盘快捷键,我在.vimrc文件中设置了这样的
nmap <leader>r :!grep -r -l * \| xargs sed -i -e 's///g'
现在从vim,在leader + r的笔划中我得到了在vim中加载的命令,我编辑如下,
:!grep -r -l <find> <file pattern> | xargs sed -i -e 's/<find>/<replace>/g'
因此,我用一个命令替换,更重要的是在vim本身
答案 9 :(得分:0)
1. :grep <search term> (or whatever you use to populate the quickfix window)
2. :cfdo s/<search term>/<replace term>/g | update
步骤1使用所需的项填充快速修复列表。在这种情况下,它与您想通过grep
进行更改的搜索词一起传播。
cfdo
在quickfix列表中的每个文件上运行以下命令。键入:help cfdo
以获得详细信息。
s/<search term>/<replace term>/g
替换每个术语。 /g
表示替换文件中的所有匹配项。
| update
在每次替换后保存文件。
我根据this answer及其评论将它们拼凑在一起,但是由于它全部集中在一个地方,因此觉得它值得自己回答。
答案 10 :(得分:0)
用法
在当前目录中搜索您要更改的文本,并将其作为子项
:Ag text
现在您已经在Vim NeoVim内部制作了小玩意