关于Vim的一个开放性问题是,是否有一种方法可以在当前项目中执行搜索/替换(如果我使用从其他编辑器继承来的这个概念,请与我一起忍受)。
例如,假设我要在项目文件中搜索方法名称,然后重命名该方法调用的所有实例。
这就是我继续进行Sublime的方式。
在Vim(可能是MacVim)中如何在不依赖其他程序(例如ack
或)的情况下进行此操作sed
?
关于Vim的一个开放性问题是,是否有一种方法可以在当前项目中执行搜索/替换(如果我使用从其他编辑器继承来的这个概念,请与我一起忍受)。
例如,假设我要在项目文件中搜索方法名称,然后重命名该方法调用的所有实例。
这就是我继续进行Sublime的方式。
在Vim(可能是MacVim)中如何在不依赖其他程序(例如ack
或)的情况下进行此操作sed
?
Answers:
有几种方法可以做到这一点。
如果要在项目树中执行搜索/替换,可以使用Vim的参数列表。
只需打开Vim,然后使用:args
命令填充参数列表。您可以传入多个文件名甚至glob。
例如,:args **/*.rb
将在当前目录中递归搜索ruby文件。注意,这也类似于使用打开Vim vim **/*.rb
。您甚至可以使用shell的find
命令通过运行以下命令来获取当前目录中所有文件的列表:
:args `find . -type f`
您可以通过单独运行来查看当前的args列表:args
。如果要从列表中添加或删除文件,可以分别使用:argadd
或:argdelete
命令。
对列表满意后,现在就可以使用Vim强大的:argdo
命令,该命令为参数列表中的每个文件运行一个命令::argdo %s/search/replace/g
以下是一些搜索提示(基于一些评论):
\<
和\>
构造,如下所示::argdo %s/\<search\>/foobar/g
/c
如果您希望Vim在替换搜索词之前要求确认,请使用搜索标志。/e
如果要跳过“未找到模式”错误,请使用搜索标志。:argdo %s/search/replace/g | update
。在这里:update
使用,因为它只会在文件更改后保存文件。如果您已经打开了缓冲区要进行搜索/替换,则可以使用:bufdo
,它为缓冲区列表(:ls
)中的每个文件运行一个命令。
该命令非常类似于:argdo
: :bufdo %s/search/replace/g
类似:argdo
和:bufdo
,有:windo
和:tabdo
分别的窗口和标签该行为。它们很少使用,但仍然有用。
\<
和\>
周围,search
以避免部分单词替换。
:cd %:p:h
。其他工作目录选项在vim.wikia.com/wiki/Set_working_directory_to_the_current_file中列出。
假设我们有一个简单的项目结构,如下所示:
greeting.txt看起来像
和info / age.txt看起来像
假设我们要用Bob替换所有出现的Sam。这是我们要做的:
设置工作目录
确保Vim的当前工作目录是项目的根目录(此处不会向您展示如何执行此操作)。
查找包含“ Sam”的文件
使用Vim的vimgrep命令搜索项目中所有Sam的出现(请注意:以**/*
递归方式搜索所有文件)
:vimgrep /Sam/gj **/*
在所有包含“ Sam”的文件中替换
现在我们要在quickfix列表中的每个文件中运行Vim的替代命令。我们可以使用:cfdo {cmd}
在quickfix列表中每个文件中执行{cmd} 的命令来执行此操作。我们要使用的特定{cmd}是substitute
或s
简称。整行如下所示:
:cfdo %s/Sam/Bob/g
如果愿意,可以添加c标志以确认所有替换:
:cfdo %s/Sam/Bob/gc
保存所有文件
:cfdo update
cfdo %s/Sam/Bob/g | update
为我解决了这一问题
hidden
选项,我建议:set hidden
您使用。
尽管不是VIM解决方案,但如果使用的是VI / VIM,则可能会发现使用CLI解决方案更容易。要更改当前目录中的所有文件,请使用perl
以下情况:
$ perl -pi -e 's/foo/bar/g' *
如果您也需要在子目录中执行此操作,我通常会perl
配合使用find
:
$ find . -name '*' -print0 | xargs -0 perl -pi -e 's/foo/bar/g'
这样做的好处是,您可以轻松地将列表进一步细化为特定的文件类型。例如,限制为python文件:
$ perl -pi -e 's/foo/bar/g' *.py
$ find . -name '*.py' -print0 | xargs -0 perl -pi -e 's/foo/bar/g'
要将短语替换为另一个短语,可以使用Vim Ex模式。
例如(ex
是的别名vim -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
)。
/c
标志确认替换可能是一个好主意。