81

grep に一致するすべてのファイルで文字列を検索して置換しようとしています:

grep -n 'foo' *次の形式で出力が得られます。

[filename]:[line number]:[text]

foogrep によって返された各ファイルについて、. に置き換えてファイルを変更したいと思いますbar

4

9 に答える 9

108

あなたが与えた例に基づいて、これはあなたが望むもののようです:

sed -i 's/foo/bar/g' *

再帰的ではありません(サブディレクトリに降りることはありません)。ツリー全体で選択したファイルを置き換える優れたソリューションとして、findを使用します。

find . -name '*.html' -print -exec sed -i.bak 's/foo/bar/g' {} \;

これ*.htmlは、ファイルが一致する必要のある式であり、元のファイルのコピーを作成した.bak後、-i拡張子は.bak(任意の拡張子にすることができます)gで、sed式の最後にあるはsedに複数のコピーを置き換えるように指示します。 1行(最初の行だけではなく)。-print検索は、どのファイルが一致していたかを示すのに便利です。これはすべて、システム上のこれらのツールの正確なバージョンによって異なります。

于 2009-01-23T01:41:57.227 に答える
70

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
于 2009-01-22T22:57:36.293 に答える
14

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/' *
于 2009-01-22T22:59:28.007 に答える
6

私は上記のソリューションまたはシステム全体の検索と数千のファイルの置換を気に入って使用しました。

find -name '*.htm?' -print -exec sed -i.bak 's/foo/bar/g' {} \;

「*.htm?」.html の代わりに、.htm ファイルと .html ファイルを同様に検索して見つけます。

.bak をシステム全体で使用されるチルダ (~) に置き換えて、バックアップ ファイルのクリーンアップを容易にします。

于 2010-07-20T18:14:03.427 に答える
4

これは、perl や find を使用する必要なく、grep を使用して機能します。

grep -rli 'old-word' * | xargs -i@ sed -i 's/old-word/new-word/g' @
于 2013-12-21T16:58:47.337 に答える
3

find . -type f -print0 | xargs -0 <sed/perl/ruby cmd>複数のスペースを含むファイル名を一度に処理し、バッチごとに 1 つのインタープリターをロードします。はるかに高速。

于 2011-12-01T13:40:56.393 に答える
1

findsedの使用について既に与えられた答え

find -name '*.html' -print -exec sed -i.bak 's/foo/bar/g' {} \;

おそらく標準的な答えです。perl -pi -e s/foo/bar/g'または、コマンドの代わりに使用できますsed

ほとんどの場合、コマンドrplの方が覚えやすいでしょう。現在のディレクトリ内のすべてのファイルを再帰的に置換 (foo -> bar) します。

rpl -R foo bar .

ほとんどの Linux ディストリビューションではデフォルトで利用できませんが、インストールは簡単です (apt-get install rplまたは同様のもの)。

ただし、正規表現と逆置換、またはファイルの名前変更と検索と置換を含むより困難なジョブの場合、私が知っている最も一般的で強力なツールはreprenです。これは、私が以前に書いた小さな Python スクリプトです。厄介な名前の変更とリファクタリングのタスク。あなたがそれを好む理由は次のとおりです。

  • ファイルの名前変更と、ファイル コンテンツの検索と置換 (ディレクトリ間のファイルの移動や新しい親ディレクトリの作成を含む) をサポートします。
  • 検索と置換の実行をコミットする前に、変更を確認してください。
  • 後方置換、単語全体、大文字と小文字を区別しない、および大文字と小文字を保持する (foo -> bar、Foo -> Bar、FOO -> BAR を置換) モードで正規表現をサポートします。
  • スワップ (foo -> bar および bar -> foo) または一意でない置換のセット (foo -> bar、f -> x) を含む、複数の置換で動作します。

例については、READMEを確認してください。

于 2015-03-22T06:15:52.003 に答える
1

これは実際には見かけよりも簡単です。

grep -Rl 'foo' ./ | xargs -n 1 -I % sh -c "ls %; sed -i 's/foo/bar/g' %";
  • grep は、ツリー (-R) を再帰的に実行し、現在のディレクトリ (./) から始まるファイル名 (-l) のみを出力します。
  • これは xargs にパイプされ、一度に 1 つずつ処理され (-n 1)、% をシェル コマンド (sh -c) でプレースホルダー (-I %) として使用します。
  • シェルコマンドでは、最初にファイル名が出力されます (ls %;)
  • 次に、sed はインライン操作 (-i)、バー (foo/bar) を使用した foo の置換 ('s/')、グローバル (/g) をファイル (再び、% で表される) に対して実行します。

簡単です。find、grep、xargs、sed、および awk をよく理解していれば、bash でのテキスト ファイルの操作に関しては、不可能なことはほとんどありません :)

于 2015-11-19T03:35:32.500 に答える
0

2022年の答え。
https://github.com/BurntSushi/ripgrep/blob/master/FAQ.md#how-can-i-search-and-replace-with-ripgrep

rg foo --files-with-matches | xargs sed -i 's/foo/bar/g'

ripgrep が foo パターンを見つけたファイル内の「foo」のすべてのインスタンスを「bar」に置き換えます。sed の -i フラグは、ファイルをその場で編集していることを示し、s/foo/bar/g は、パターン foo の bar への置換を実行していること、およびこの置換をグローバルに実行していることを示します (各ファイルのパターン)。

于 2022-01-13T09:14:37.660 に答える