Vimの代替コマンドについて知りました...
:%s/replaceme/replacement/gi
そしてvimgrep ...
:vimgrep /findme/gj project/**/*.rb
ディレクトリ下のすべてのファイルを置き換えるためにそれらを組み合わせる方法はありますか?
私はVimユーザーですが、通常、find
とsed
を使用してこの種のことを行います。 sed
の正規表現構文はVimの構文に似ています(どちらもed
の子孫です)が、同一ではありません。 GNU sedを使用すると、インプレース編集に-i
を使用することもできます(通常、sed
は変更されたバージョンをstdoutに出力します)。
例えば:
find project -name '*.rb' -type f -exec sed -i -e 's/regex/replacement/g' -- {} +
少しずつ:
project
=「プロジェクト」ツリーを検索-name '*.rb'
=名前が「* .rb」に一致するもの-type f
=および通常のファイル(ディレクトリ、パイプ、シンボリックリンクなどではない)-exec sed
= sed
を次の引数で実行します:-i
=インプレース編集あり-e 's/regex/replacement/g'
= "substitute"コマンドを実行します(Vimの:s
とほぼ同じですが、%
がないことに注意してください-sed
のデフォルトです)--
=フラグの終わり、ファイル名はここから始まります{}
=これはfind
に、見つかったファイル名をsedのコマンドラインに配置する必要があることを伝えます+
=これはfind
に-exec
アクションが終了したことを伝え、引数をできるだけ少ないsed
呼び出しにグループ化したい(一般に実行よりも効率的)ファイル名ごとに1回)。ファイル名ごとに1回実行するには、\;
の代わりに+
を使用できます。これは、GNU sed
およびfind
を使用した一般的な解決策です。これは、特別な場合に少し短縮できます。たとえば、名前パターンが-type f
を省略できるディレクトリとは一致しません。-
で始まるファイルがないことがわかっている場合は、--
を省略できます。 これが私が投稿した回答ですfind
で検出されたファイル名を他のコマンドに渡す方法の詳細を含む別の質問へ。
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
10000@a #repeat the macro 10000 times, or until stopped by
#an "error" such as reaching the end of the list
:set noautowrite
私はそれをテストしていません、それでそれは少し微調整を必要とするかもしれません-あなたが最初に台無しにされても構わないいくつかのファイルでそれをテストしてください。
Sedに対するこれの利点は、Vimの正規表現の方が強力であり、cオプションを:sに追加して、各置換を検証できることです。
編集:間違っていたので元の投稿を変更しました。私は:1vimgrepを使用して各ファイルの最初の一致を見つけましたが、ドキュメントを誤って読みました-すべてのファイルで1つの一致しか見つけられません。
1つの方法は、置換を実行するすべてのファイル(または任意のコマンド)を開き、:bufdo <cmd>
を実行することです。これにより、開いているすべてのバッファーで<cmd>
が実行されます。
それだけを行うように努めるプラグインがあります: Vimgrep Replace 。
ああ、待って...他にもあります: Global Replace 、 EasyGrep 。
プラグインなしのソリューションの場合、argdo
の出力を引数リスト(vimgrep
で設定できます)に取得できれば、おそらくargs
が役立つでしょうが、私には思えません詳細を把握する。誰かがアイデアを取り入れて改善してくれたら幸いです...だからここにあります。
最初のプラグインの背後にある基本的な考え方(他のプラグインもそうだと思います...)は、最初にvimgrep
を使用し、次に:cnext
とし、各行に置換コマンドを適用します。これを実行するための関数は、.vimrcに配置するのに十分小さい可能性があります。 (多分あなたはプラグインのソースから一つを持ち上げることができますか?)
(私はhgimenezが解決策にあるかもしれないと思いますが、それが適切であるかどうかはおそらく処理されるファイルの数に依存します...プラグインは関係なく大丈夫でなければなりません。)
Vimgrepと置換を組み合わせるという元の質問に答えるには:
:vimgrep /pattern/ ./**/files # results go to quickfix list
:set autowrite # auto-save when changing buffers
:silent! cdo %s/replaceme/replacement/gic # cdo draws filenames from quickfix list
:set noautowrite
各置換を確認したくない場合は、c
of gic
を省略します(この場合、find
とsed
を使用して、 @LaurenceGonsalves)。
これは、少数のファイルで機能します。
vim `find。 -type f `
:bufdo%s /パターン/置換/ gec |更新