我发现了Vim的替代命令如何在Vim中的目录中递归搜索和替换?
:%s/replaceme/replacement/gi
而且使用vimgrep ...
:vimgrep /findme/gj project/**/*.rb
有没有办法给他们为了做所有的文件替换下结合目录?
我发现了Vim的替代命令如何在Vim中的目录中递归搜索和替换?
:%s/replaceme/replacement/gi
而且使用vimgrep ...
:vimgrep /findme/gj project/**/*.rb
有没有办法给他们为了做所有的文件替换下结合目录?
尽管我是Vim用户,但我通常使用find
和sed
来处理这类事情。 sed
的正则表达式语法与Vim(它们都是ed
的后代)类似,尽管不完全相同。使用GNU sed,您还可以使用-i
进行就地编辑(通常sed
会将修改后的版本发送到stdout)。
例如:
find proj -name '*.rb' -type f -exec sed -i -e 's/regex/replacement/g' -- {} +
一块一块:
proj
=搜索-name '*.rb'
=东西的名字匹配 '* .RB'-type f
=并且是常规文件(不是目录,管道,符号链接等)。)-exec sed
=运行sed
这些论点:
-i
=与就地编辑-e 's/regex/replacement/g'
=执行 “替换” 命令(几乎相同的Vim的:s
,但注意不足%
- 它在sed
默认)标志的--
=结束,文件名从这里开始{}
=这就告诉find
是TH它发现Ë文件名应放在sed中的命令行这里+
=这就告诉find
该-exec
动作完成,我们要组参数成少数sed
调用越好(一般比一次运行更高效每个文件名)。要为每个文件名运行一次,您可以使用\;
而不是+
。这与GNU sed
和find
一般的解决方案。在特殊情况下可以缩短一点。例如,如果你知道你的名字模式不匹配任何目录,你可以省略-type f
。如果您知道所有文件都不以-
开头,则可以省略--
。 Here's an answer I posted to another question with more details on passing filenames found with find
to other commands.
确保并在给予'sed'之前测试你的'find' - 如果它过于包容,这可能非常糟糕。给'sed''-c'('--copy')选项也是一个好主意,这将防止它与只读文件混淆。 – Cascabel 2010-01-21 23:06:17
@BroSlow够公平的。我已经更新了答案,以便更安全/更一般。 (也就是说,在Linux上,至少ARG_MAX是相当大的,对于问题中描述的用例,使用空格或特殊字符的文件名会非常奇怪。) – 2014-11-10 00:49:47
如果使用此方法,则不能使用该构造,因为sed不支持它,你可以使用'vim -c'%/ regex/replacement/gc'-c'wq' - {} \;'这样你就可以确认你的改变了 – Funonly 2015-04-23 09:22:58
有一个插件正在努力做到这一点:Vimgrep Replace。
哦,等等......还有其他的:Global Replace,EasyGrep。
对于一个没有插件的解决方案,或许argdo
将有助于如果你能得到vimgrep
的输出到参数列表(可以用args
设置),但我似乎无法弄清楚的细节。如果有人采纳了这个想法并对其进行改进,我会很高兴......所以在这里。
第一个插件(我猜别人也是......)的基本思想是首先使用vimgrep
,然后在:cnext
之间循环匹配,并在每行上应用替换命令。完成此功能的函数可能足够小,可以放入.vimrc中。 (也许你可以举一个插件的来源?)
(我想hgimenez可能是一个解决方案,但不管它是否合适可能取决于要处理的文件数量......插件应该没问题。)
谢谢,但arrrrgh!有没有办法做到这一点,而无需安装另一个#!*&%插件? – Ethan 2010-01-21 21:48:33
@Ethan:我感觉你。 :-)我认为必须有一种方法涉及:args,:argdo,:copen或其他......我只是不使用vimgrep足够以前对它有过多的考虑,似乎无法将它们放在一起对你来说完美的解决方案。但我仍在尝试,所以也许我会想出一些东西并进行编辑。 – 2010-01-21 21:52:53
噢,好吧......我似乎无法找到一个干净简单的无插件解决方案,或者确定地告诉我自己没有任何插件。我的Vim-fu让我失望了! :-(插件的确看起来不错,但也许它们值得一试...... – 2010-01-21 22:32:30
一种方法是打开所有要运行替换(或任何命令)的文件,然后运行:bufdo <cmd>
,它将在所有打开的缓冲区上运行<cmd>
。
您可以运行使用vimgrep然后录制去在使用vimgrep输出每一行,并没有替换,像这样一个宏:(!不要键入#评论)
:set autowrite #automatically save the file when we change buffers
:vimgrep /pattern/ ./**/files
qa #start recording macro in register a
:s/pattern/replace/g #replace on the current line
:cnext #go to next matching line
q #stop recording
[email protected] #repeat the macro 10000 times, or until stopped by
#an "error" such as reaching the end of the list
:set noautowrite
我没有测试过它,所以它可能需要一点调整 - 在一些你不介意首先搞砸的文件上测试它。
这个优于sed的优点是Vim正则表达式更加强大,您可以添加c选项来:验证每个替换项。
编辑: 我修改了原来的帖子,因为它是错误的。我正在使用:1vimgrep来查找每个文件中的第一个匹配项,但我误读了文档 - 它仅在所有文件中找到一个匹配项。
很酷!在寻找单一的表达解决方案时,我从来没有停下来考虑一个宏观...让我现在感觉有点傻。 +1。 :-) – 2010-01-23 14:36:58
你刚刚救了我几个小时的工作,谢谢! :D我需要将xml文件中的值复制到文件的另一部分,然后小写 - 超过200个文件。 – Jason 2012-05-04 15:32:30
这适用于少量文件。
vim`find。 -type f`
:bufdo%s/pattern/replacement/gec |更新
[Here](http:// stackoverflow。com/a/13944042/834176)是递归搜索和替换的一种方式,但仅限于版本控制下的文件(如果您确实想要搜索目录下的所有文件,可以很容易地进行推广)。 – 2012-12-19 01:06:51