Linuxマシンでgrepに一致するすべてのファイルの文字列を検索して置換しようとしています。私がやりたいことのいくつかの部分を持っていますが、それらをすべて一緒につなげるのが最善かどうかはわかりません。
grep -n 'foo' *
は次の形式で出力します。
[filename]:[line number]:[text]
Grepによって返される各ファイルについて、「foo」を「bar」に置き換えて、結果をファイルに書き戻したいと思います。それを行う良い方法はありますか?たぶん派手なパイプラインですか?
Grepに一致するすべてのファイルの文字列を検索して置換するということですか?
Perl -p -i -e 's/oldstring/newstring/g' `grep -ril searchpattern *`
編集
これはかなり人気のある質問のように思えるので、更新すると思いました。
最近はほとんどack-grep
より使いやすいため。したがって、上記のコマンドは次のようになります。
Perl -p -i -e 's/old/new/g' `ack -l searchpattern`
ファイル名の空白を処理するには、次を実行します:
ack --print0 -l searchpattern | xargs -0 Perl -p -i -e 's/old/new/g'
ack-grep
。検索をHTMLファイルのみに制限するとします。
ack --print0 --html -l searchpattern | xargs -0 Perl -p -i -e 's/old/new/g'
また、空白が問題にならない場合はさらに短くなります。
Perl -p -i -e 's/old/new/g' `ack -l --html searchpattern`
Perl -p -i -e 's/old/new/g' `ack -f --html` # will match all html files
あなたが与えた例に基づいて、これはあなたが望むもののようです:
sed -i 's/foo/bar/g' *
再帰的ではありません(サブディレクトリに降りません)。ツリー全体で選択したファイルを置換するニースソリューションの場合は、findを使用します。
find . -name '*.html' -print -exec sed -i.bak 's/foo/bar/g' {} \;
*.html
はファイルが一致しなければならない式、.bak
後に -i
は、.bak拡張子(任意の拡張子)を使用して元のファイルのコピーを作成し、sed式の最後にあるg
は、sedに1行で複数のコピーを置き換えるように指示します最初のものだけより)。 -print
を見つけることは、どのファイルが一致していたかを示すのに便利です。これはすべて、システム上のこれらのツールの正確なバージョンに依存します。
sed(1)
に-i
オプションがある場合、次のように使用します。
for i in *; do
sed -i 's/foo/bar/' $i
done
そうでない場合は、使用する言語に応じて、次の方法にいくつかのバリエーションがあります。
Ruby -i.bak -pe 'sub(%r{foo}, 'bar')' *
Perl -pi.bak -e 's/foo/bar/' *
私は上記のソリューションまたはシステム全体の検索を好み、使用し、数千のファイル間で置き換えました。
find -name '*.htm?' -print -exec sed -i.bak 's/foo/bar/g' {} \;
「* .htm?」 .htmlの代わりに、.htmファイルと.htmlファイルを同様に検索して見つけます。
バックアップファイルのクリーンアップを容易にするために、.bakをよりシステム全体で使用されるチルダ(〜)に置き換えます。
これは、Perlを使用したり検索する必要なく、grepを使用して機能します。
grep -rli 'old-Word' * | xargs -i@ sed -i 's/old-Word/new-Word/g' @
find . -type f -print0 | xargs -0 <sed/Perl/Ruby cmd>
は、バッチごとに1つのインタープリターをロードして、複数のスペースに含まれるファイル名を一度に処理します。はるかに高速。
これは実際には見かけよりも簡単です。
grep -Rl 'foo' ./ | xargs -n 1 -I % sh -c "ls %; sed -i 's/foo/bar/g' %";
簡単です。 find、grep、xargs、sed、awkを十分に理解している場合、bashでのテキストファイル操作に関してはほとんど何も不可能です:)
findおよびsedを使用することについて既に与えられた答え
find -name '*.html' -print -exec sed -i.bak 's/foo/bar/g' {} \;
おそらく標準的な答えです。または、sed
コマンドの代わりにPerl -pi -e s/foo/bar/g'
を使用できます。
ほとんどのクイックユースでは、コマンドrplのほうが覚えやすい場合があります。以下は、現在のディレクトリ内のすべてのファイルでの置換(foo-> bar)です。
rpl -R foo bar .
ほとんどのLinuxディストリビューションではデフォルトでは使用できませんが、インストールは簡単です(apt-get install rpl
または同様の機能)。
ただし、正規表現と逆置換、またはファイル名の変更と検索と置換を含むより厳しいジョブの場合、私が知っている最も一般的で強力なツールはrepren、小さなPython私がしばらく前に、より厄介な名前変更とリファクタリングのタスクのために書いたスクリプト。あなたがそれを好むかもしれない理由は: