すべてのプロジェクトファイルでVimを検索して置換する


117

Vimのすべてのプロジェクトファイルで検索と置換(確認あり)を行うための最良の方法を探しています。「プロジェクトファイル」とは、現在のディレクトリにあるファイルを意味し、その一部を開く必要はありません。

これを行う1つの方法は、現在のディレクトリにあるすべてのファイルを単に開くことです。

:args ./**

次に、開いているすべてのファイルを検索して置換します。

:argdo %s/Search/Replace/gce

しかし、これを行うと、Vimのメモリ使用量が数十MBから2 GBを超えるまでに急増し、私にとってはうまくいきません。

私も持っているEasyGrepのプラグインがインストールされていますが、それは動作しません、どちらかほとんどない、それは私のプレスまで、すべての出現、またはそれだけでハングアップを見つけることができませんCtrlC。これまでのところ、このタスクを実行するための私の優先する方法は、検索用語のack-grepです。クイックフィックスウィンドウを使用して、用語を含み、以前に開かれていないファイルを開き、最後に:bufdo %s/Search/Replace/gce

私は、これに使用できる優れた機能するプラグイン、または現在使用しているものよりも簡単なコマンド/コマンドシーケンスのいずれかを探しています。


1
@Cascabelこのコメントを書いたため、vi.stackexchange.comサイトがあります。
Flimm

回答:


27

Greplaceは私に適しています。

githubには病原体対応バージョンもあります。


8
インストールすると、:Gsearchやのような他のコマンドが表示されますが、入力:Gbuffersearchするとが表示され:GreplaceますNot an editor command: Greplace
Ramon Tayag、2011

ドキュメントによると、構文は次のとおりです。:Gsearch [<grep-option(s)>] [[<pattern>] [<filename(s)>]] あなたは、たとえば、使用して再帰的な検索を行うことができるように::Gsearch -r pattern dir/
vitorbal

Greplaceについて私が嫌いなのは、パターンがファイル名に含まれていると、Greplaceが失敗するということです。
ダニエル

2
ここ6年後には何も珍しいことはありませんが、このプラグインは、3年以上前のいくつかの新しい回答(github.com/yegappan/greplace)の最後の更新と比較すると、かなり古くなっています。私はSidによって組み込みのソリューションをチェックアウトするかもしれません:stackoverflow.com/a/38004355/2224331(別のアカウントでは私ではありません。偶然です:P)
SidOfc

99

ここでのもう1つの大きなオプションは、単にvimを使用しないことです。

sed -i 's/pattern/replacement/' <files>

または、ファイルのリストを生成する方法がある場合は、おそらく次のようになります。

find . -name *.cpp | xargs sed -i 's/pattern/replacement/'
grep -rl 'pattern1' | xargs sed -i 's/pattern2/replacement/'

等々!


ありがとう!私は本当にこの古い学校のコマンドラインのことを学ぶ必要があります。これが最良の答えだと思います。これらの正規表現はperlの正規表現かvimの正規表現ですか、それとも他の種類の正規表現ですか?
Eric Johnson

2
@EricJohnson:それらは... sed正規表現であり、本質的にはPOSIX.2の基本的な正規表現ですが、厳密にはそうではありません(これはマンページにあります)\n。したがって、これらはgrep正規表現とほとんど同じです。
Cascabel 2012年

sedコマンドに-iがある理由はありますか?マニュアルページには、それが拡張子を指定するためのものであると記載されていますが、実際には指定しないようです。
davekaro 2013

「s / pattern / replacement /」が拡張機能のように見えますが、理解できたと思います。
davekaro 2013

11
Mac OS Xで私のために機能した唯一のsedコマンドは次のfind . -type f | LANG=C xargs sed -i '' 's/SEARCH/REPLACE/g'
とおりです。– ghodss

74

編集:cfdo代わりにコマンドを使用してcdo、これを実行するために実行されるコマンドの量を大幅に削減します(各ファイルでコマンドを実行しcdoながら各要素でコマンドを実行するためcfdo

最近追加されたcdoコマンドのおかげで、grepインストールしたツールを使用して2つの簡単なコマンドでこれを行うことができます。追加のプラグインは必要ありません!:

1. :grep <search term>
2. :cdo %s/<search term>/<replace term>/gc
3. (If you want to save the changes in all files) :cdo update

(コマンドが入力cdoするquickfixリストの各用語に対して、指定されたコマンドを実行しますgrep。)

c毎回確認せずに各検索語を置き換える場合は、2番目のコマンドの最後にあるを削除します)


12
さらに:cdo update、すべてのファイルに変更を保存するために追加できます。
Zhe Li

1
ただし、現在のバッファが変更されると、次のバッファに切り替える前に、保存されないことを警告するために一時停止します。
lfree

1
@ありがとう、私はそれを答えに追加しました。@lfree私は個人的に各変更を確認することを好みますがc、2番目のコマンドの最後でを削除して(を使用するだけg)、確認を求めずに検索と置換を行うことができます
Sid

1
:cdo%s /検索用語/置換用語/ gは最初の出現を置き換えるだけですが、私のvimの2番目の出現では機能しません
sunxd

3
を使用するためにupdate、私は次のことをしなければなりませんでした:cdo %s/<search term>/<replace term>/g | update
gabe

34

GNUサブセットではなく、より強力な完全なPerl正規表現を利用するために、ackとPerlを使用してこの問題を解決することにしました。

ack -l 'pattern' | xargs perl -pi -E 's/pattern/replacement/g'

説明

ack

ACKが混在ある素晴らしいコマンドラインツールでありgrepfindおよび完全なPerlの正規表現(だけでなく、GNUサブセット)。純粋なPerlで記述され、高速で、構文の強調表示があり、Windowsで動作し、従来のコマンドラインツールよりもプログラマーにとって使いやすくなっています。Ubuntuにをインストールしsudo apt-get install ack-grepます。

xargs

Xargsは古いUNIXコマンドラインツールです。標準入力から項目を読み取り、指定されたコマンドを実行してから、標準入力で読み取った項目を実行します。したがって、基本的に、ackによって生成されたファイルのリストは、perl -pi -E 's/pattern/replacemnt/g'コマンドの最後に追加されます。

perl -pi

Perlはプログラミング言語です。-pオプションを指定すると、Perlはプログラムの周りにファイル名引数を反復するループを作成します。-iオプションを指定すると、Perlはファイルをその場で編集します。これを変更して、バックアップを作成できます。-Eオプションを指定すると、Perlはプログラムとして指定された1行のコードを実行します。私たちの場合、プログラムはPerlの正規表現による置換にすぎません。Perlコマンドラインオプションの詳細についてperldoc perlrun。Perlの詳細については、http://www.perl.org/を参照してください


cygwinの行末でも機能するので、この回答が好きです。変更された行の最後に\ rを追加することに注意してください。ただし、sedを使用すると、すべての改行が置き換えられ、diffが使用できなくなります。Perlはもう少し正気です、そしてこれは検索と置換のための本当に素晴らしい1行です。ありがとう!
アンドリュー2012年

@andrew、私はあなたのケースで何が間違っているのか正確にはわかりません。正規表現で\ nの代わりに\ Rを使用するのに役立ちますか?perldoc.perl.org/perlrebackslash.html#Miscの \ Rセクションを参照してください。また、perldoc.perl.org / perlre.html#Regular-Expressionsも試してください。Perlは非常にクロスプラットフォームであり、行末が壊れないようにする方法は確かにあります。
エリックジョンソン

私の正規表現には改行がありません。これらのプログラムのcygwinバージョンは、変更された各行の終わりに\ rを自動的に追加します。正規表現に一致しなくても、sedはすべての行を変更するのに対し、sedはすべての行を変更するため、perlバージョンは特に気に入っています。
アンドリュー

ファイルのパスにスペースが含まれている場合はどうなりますか?
shengy 14

23

多分これを行います:

:noautocmd vim /Search/ **/*
:set hidden
:cfirst
qa
:%s//Replace/gce
:cnf
q
1000@a
:wa

説明:

  • :noautocmd vim /Search/ **/*速度を上げるために、autocmds()をトリガーせずに、cwdのすべてのサブディレクトリにあるすべてのファイルのlookup(vimはの省略形vimgrep)パターン:noautocmd
  • :set hidden ⇒変更されたバッファをウィンドウに表示しないようにする(vimrcにある可能性があります)
  • :cfirst ⇒最初の検索結果にジャンプ
  • qa ⇒レジスタaへのマクロの記録を開始します
  • :%s//Replace/gce⇒最後の検索パターン(まだ/Search/その時点で)のすべての出現箇所を次のものに置き換えますReplace
    • 同じ行で複数回(gフラグ)
    • ユーザー確認あり(cフラグ)
    • パターンが見つからない場合はエラーなし(eフラグ)
  • :cnfvimコマンドで作成されたリストの次のファイルにジャンプ
  • q ⇒マクロの記録を停止
  • 1000@a ⇒レジスターに保存されたマクロを1000回再生
  • :wa ⇒変更されたすべてのバッファを保存します

*編集* Vim 8 way:

Vim 8以降では:cfdo、quickfixリスト内のすべてのファイルを反復処理するため、より良い方法があります。

:noautocmd vim /Search/ **/*
:set hidden
:cfdo %s//Replace/gce
:wa

あなたは私たちより少ない死すべき者のためにもう少し説明したいと思うかもしれません。毎回この「シーケンス」を行う必要があるかどうかは、私にはわかりません。私は錆びた古いDelphi 5を使用する方が速いので、何かが欠けているに違いありません。
Lieven Keersmaekers、2011年

1
@リーベン:あ​​なたは正しい、これはコメントなしでは少しあいまいです。いくつかの説明を展開します。
Benoit

+1ですが、vim多くの点で私を勝ち取りましたが、これでPowerGrepに固執すると思います。
Lieven Keersmaekers、2011年

あなたの答えとすべてのコマンドの説明をありがとう、本当に感謝しています。これにはプラグインを使用したいので、他の回答を受け入れます。
psyho 2011年

質問をする人のレベルとこの回答を理解するために必要なレベルとの間に差があることを考えると、混乱を引き起こすため、これをマークダウンしました。
ロイドムーア

22

移入:argsシェルコマンドから

(一部のオペレーティングシステムでは1)):argsシェルコマンドを介してファイルを提供することが可能です。

たとえば、ack 2がインストールされている場合、

:args `ack -l pattern`

「パターン」を含むファイルのリストを返すようackに要求し、これらを引数リストに配置します。

または、プレーンなol 'grepを使用すると、次のようになります。

:args `grep -lr pattern .`  


その後:argdo、OPの説明に従って使用できます。

:argdo %s/pattern/replacement/gce


移入:argsQuickFixリストから

また、現在のクイックフィックスリストからarglistにデータを入力する簡単なユーザー定義コマンドを説明する関連質問に対するnelstromの回答も確認してください。これは、多くのコマンドとその出力QuickFixリスト(で終わるプラグインで素晴らしい作品:vimgrep:Ack3:Ggrep4)。

プロジェクト全体の検索を実行するシーケンスは、次のようにして実行できます。

:vimgrep /pattern/ **/*
:Qargs 
:argdo %s/findme/replacement/gc

ここで:Qargs、quickfixリストからarglistを生成するユーザー定義コマンドの呼び出しです。

次のディスカッションには、このワークフローを2つまたは3つのコマンドに変換する単純なプラグインへのリンクもあります。

リンク集

  1. :h {arglist} -vimdoc.sourceforge.net/htmldoc/editing.html# {arglist }
  2. ACK - betterthangrep.com/
  3. ack.vim - github.com/mileszs/ack.vim
  4. 逃亡 - github.com/tpope/vim-fugitive

1
argdoが書き込みの問題がある最初のファイルの後で停止する
frankster


5

外部依存関係の導入を気にしなければ、私はプラグインctrlsf.vimackまたはagに依存)を作成してその仕事をしました。

これは、ack / agからの検索結果をフォーマットして表示し、結果バッファーの変更をディスク上の実際のファイルに同期させることができます。

多分次のデモはより多くを説明します

ctrlsf_edit_demo


3
1. :grep <search term> (or whatever you use to populate the quickfix window)
2. :cfdo %s/<search term>/<replace term>/g | update

ステップ1で、必要な項目をクイックフィックスリストに追加します。この場合、を介して変更したい検索語句とともに伝播されますgrep

cfdoクイックフィックスリストの各ファイルに対して次のコマンドを実行します。:help cfdo詳細を入力してください。

s/<search term>/<replace term>/g各用語を置き換えます。/gファイル内のすべての出現箇所を置き換えることを意味します。

| update 置換するたびにファイルを保存します。

私はこの回答とそのコメントに基づいてこれをつなぎ合わせましたが、すべてが1か所にあるため、独自の回答に値するものだと感じました。


NeoVimの私にとっては、上の行2でわずかな変更を行う必要がありました。を使用し2. :cfdo %s/<search term>/<replace term>/g | updateない%場合、最初に出現したパターンのみが置き換えられます。
カリームエルガウィ

カリームに感謝します。%s通常のvimでも動作するので、私は答えを更新しました。
カイルHeironimus

0

基本的に、私は単一のコマンドで、より重要なことにはvim自体で置換を望んでいました

@Jefromi回答に基づいて、次のように.vimrcファイルに設定したキーボードショートカットを作成しました

nmap <leader>r :!grep -r -l  * \| xargs sed -i -e 's///g'

今、vimから、leader + rのストロークで、vimにロードされたコマンドを取得します。

:!grep -r -l <find> <file pattern> | xargs sed -i -e 's/<find>/<replace>/g'

したがって、私は単一のコマンドで置き換えますが、より重要なのはvim自体の中で行います


そして、私は実際にはgrepの代わりにagを使用しています
deepak '13 / 12/14
弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.