关于Vim的一个开放性问题是,是否有一种方法可以在当前项目中执行搜索/替换(如果我使用从其他编辑器继承来的这个概念,请与我一起忍受)。

例如,假设我要在项目文件中搜索方法名称,然后重命名该方法调用的所有实例。

这就是我继续Sublime的方法。



如何在Vim(可能是MacVim)中执行此操作,而不依赖其他程序(例如acksed)?

#1 楼

有几种方法可以执行此操作。

在当前目录中

如果要在项目树中执行搜索/替换,可以使用Vim的参数列表。 />
只需打开Vim,然后使用:args命令填充参数列表。您可以传入多个文件名甚至glob。例如,:args **/*.rb将在当前目录中递归搜索ruby文件。注意,这也类似于用vim **/*.rb打开Vim。您甚至可以通过运行以下命令,使用外壳程序的find命令获取当前目录中所有文件的列表:
本身。如果要从列表中添加或删除文件,可以分别使用:args:argadd命令。

对列表满意后,现在可以使用Vim强大的:argdelete命令,该命令可以运行参数列表中每个文件的命令::argdo以下是一些搜索提示(基于一些注释):


使用单词边界如果要搜索“ foo”而不是“ foo_bar”。在搜索模式周围使用:argdo %s/search/replace/g\<构造,如下所示:\>

如果希望Vim在替换搜索词之前要求确认,请使用:argdo %s/\<search\>/foobar/g搜索标志。如果要跳过“未找到模式”错误。
还可以在执行搜索后选择保存文件:/c。在这里,使用/e是因为它仅在文件已更改的情况下保存文件。 ,您可以使用:argdo %s/search/replace/g | update,它对缓冲区列表(:update)中的每个文件运行一个命令。

该命令与:bufdo非常相似::ls

:argdo:bufdo %s/search/replace/g类似,分别有:argdo:bufdo分别作用于窗口和选项卡。它们很少使用,但仍然有用。

评论


使用/ c标志确认替换可能是一个好主意。

– romainl
15年3月29日在11:20

我还建议在搜索周围使用单词边界\ <和\>以避免部分单词替换。

–tommcdo
2015年3月29日14:02

另一种意见是,默认情况下,vim的工作目录是您启动vim的位置,而不是当前文件的目录。您可以使用:cd%:p:h将工作目录设置为当前文件。其他工作目录选项在vim.wikia.com/wiki/Set_working_directory_to_the_current_file中列出。

–studgeek
16年7月21日在16:37

#2 楼

假设我们有一个简单的项目结构,如下所示:



greeting.txt看起来像
看起来像



假设我们要用info/age.txt替换所有出现的Sam。我们将执行以下操作:

1。设置工作目录


确保Vim的当前工作目录是项目的根目录:

     :cd {path to root directory}


可以使用Bob打印当前工作目录,并确保它正确无误。

2。查找包含'Sam'的文件


使用Vim的:pwd命令搜索项目中所有出现的:vimgrep

    :vimgrep /Sam/gj **/*


注意:



Sam是夹在两个正斜杠之间的搜索“模式”
Sam表示以递归方式搜索所有文件
**/*标志说要搜索每一行中的所有匹配项(实际上这在这里是过高的,但是也不会造成伤害)
g标志可以防止vim自动跳转到第一个匹配项

使用j的所有实例填充快速修复列表。如果要查看快速修复列表,可以使用Vim命令Sam



3。在所有包含'Sam'的文件中替换


现在,我们想在quickfix列表中的每个文件中运行Vim的:copen命令。我们可以使用:substitute命令执行此操作,该命令在quickfix列表中的每个文件中执行:cfdo {cmd}。我们要使用的特定{cmd}简称为{cmd}:substitute。整个行看起来像:

    :cfdo %s/Sam/Bob/gc


注释:


:s是指定每行的行范围
/> %标志指示替换每行中的所有匹配项
g标志使vim要求您单独确认每个替换
(您可能要忽略它)

3。保存所有文件


    :cfdo update


评论


我更喜欢这个。它很简单,并且可以与Ack(或填充QuickFix窗口的任何插件)一起使用。

– Zuhaib
16年11月28日在16:07

这是一个很好的答案

– Peoplee
16 Dec 7'在17:21

正在执行“ cfdo%s / Sam / Bob / g”,得到“自上次更改以来没有写入” |更新为我修复

– hakunin
17年12月14日在11:14

@hakunin我建议您将隐藏选项设置为:set hidden(如果尚未设置)。

– Niko Bellic
18年1月8日在22:57

这是更可移植的答案,可在任何OS上使用。

–赛义德
20年6月10日在23:10

#3 楼

尽管不是VIM解决方案,但如果使用的是VI / VIM,则可能会发现使用CLI解决方案更容易。要更改当前目录中的所有文件,请使用perl,因为它是针对以下情况而制作的:具有perlfind

$ perl -pi -e 's/foo/bar/g' *


这样做的好处是,您可以轻松地将列表进一步细化为特定文件类型。例如,限制为python文件:

$ find . -name '*' -print0 | xargs -0 perl -pi -e 's/foo/bar/g'


#4 楼

要用另一种替换短语,可以使用Vim Ex模式。例如(exvim -E的别名):

$ ex -s +'bufdo!%s/foo/bar/g' -cxa *.*


递归在bash / zsh中(设置了globstar,例如shopt -s globstar):

$ ex -s +'bufdo!%s/foo/bar/g' -cxa **/*.*
$ ex -s +'n **/*.*' +'bufdo!%s/foo/bar/g' -cxa


递归(使用find并忽略诸如.git文件的隐藏文件):

$ find . -type f -not -path '*/\.*' -exec ex -s +'bufdo!%s/foo/bar/g' -cxa {} "+"


注意::bufdo命令不是POSIX。

注意:语法-not -path '*/\.*'用于忽略隐藏文件(例如.git)。

评论


注意bufdo不是POSIX pubs.opengroup.org/onlinepubs/9699919799/utilities/ex.html

–史蒂芬·潘妮(Steven Penny)
16年4月17日在0:35

#5 楼

这是使用findex编辑器的shell命令(不使用:bufdo):

find . -name '*.rb' -exec ex +'%s/foo/bar/ge' -V1 -scwq! {} ';'


这将在当前位置(递归)编辑所有*.rb文件,并将foo替换为bar