我發現了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