sedとgrep / egrepを使用した検索と置換


97

次のegrep -Rように、約10のユニオンを含む正規表現を続けて使用しています .jpg | .png | .gif。これはうまくいきます。今、見つかったすべての文字列を.bmp

のようなものを考えていました

egrep -lR "\.jpg|\.png|\.gif" . | sed "s/some_expression/.jpg/" file_it_came_form

したがって、ここでの問題は、同様のユニオン正規表現sedをどのように実行するか、および入力を取得したファイルへの変更を保存するように指示する方法です。


2
ディレクトリ階層内の複数のファイルを検索および置換する方法を検索しているときに、この質問を見つけました。私の状況の他の人のために、rplを試してください
チタニウム

rplが機能し、本当に覚えやすいことに感謝します.. rpl old_string new_string target_files
cesarpachon 2015年

回答:


183

次のコマンドを使用します。

egrep -lRZ "\.jpg|\.png|\.gif" . \
    | xargs -0 -l sed -i -e 's/\.jpg\|\.gif\|\.png/.bmp/g'
  • egrep:拡張正規表現を使用して一致する行を見つける

    • -l:一致するファイル名のみをリスト

    • -R:指定されたすべてのディレクトリを再帰的に検索します

    • -Z\0レコードセパレータとして使用

    • "\.jpg|\.png|\.gif":文字列の1つに一致する".jpg"".gif"または".png"

    • .:現在のディレクトリで検索を開始します

  • xargs:stdinを引数としてコマンドを実行します

    • -0\0レコード区切り記号として使用します。これは、一致させることが重要である-Zegrepと、入力ファイル名にスペースや改行でだまされることを避けるために。

    • -l:コマンドごとに1行をパラメーターとして使用する

  • seds tream ed itor

    • -i:バックアップを作成せずに入力ファイルを出力に置き換えます

    • -e:次の引数を式として使用します

    • 's/\.jpg\|\.gif\|\.png/.bmp/g':文字列の出現をすべて置き換える".jpg"".gif"または".png"".bmp"


|以外はすべて機能します sed部分に。それが理にかなっているのでなぜ私は理解していません... xargsの-lの部分は私にエラーを与えていたのでそれを取り出しました、それは関連しているのでしょうか?
Ori

このコマンドを実行すると、処理するすべてのファイルの最後に改行が追加されることがわかりました。
チタニウム

@titanumdecoy:この動作を再現することができませんでした。どのバージョンのsedを使用していて、どのOSを使用していますか?
David Schmitt

1
@DavidSchmitt:おそらくsed -r拡張正規表現に使用したいでしょう。その時点で、パターンはegrepで使用されているものと一致するため、再利用するために変数に配置することができます。
bukzor

このコマンドを使用すると、作成したライブラリのアプリからヘッダーファイルをコピーする時間を数時間節約できました。これは素晴らしいです:)これがegrep -lRZ "\ .h $"を使用したコマンドです。| xargs -0 tar -cvf headers.tar | (cp headers.tar headers; cd headers; tar xf headers.tar;)
Lazy Coder

11

正直なところ、私がsedで適切なタスクを実行するのが大好きなように、これは間違いなくperlのタスクです-この種のワンライナーにとっては、特に「それを元の場所に書き戻す」(perlの-iスイッチがそれを行うための)方が本当に強力ですあなた、そしてオプションとして、.bakが追加された古いバージョンを維持することもできます-i.bak。代わりに使用してください)。

perl -i.bak -pe 's/\.jpg|\.png|\.gif/.jpg/

sed(可能な場合でも)またはawkでの複雑な作業ではなく...


6
sedはperlと同様に-iを使用します。
Stobor 2009

@Stobor-正規表現の置換文字列を入力したときのperl操作が、正規表現オプションをsed..それには限界がありました。
meder omuraliev

10

これを行う別の方法

find . -name *.xml -exec sed -i "s/4.6.0-SNAPSHOT/5.0.0-SNAPSHOT/" {} \;

上記のコマンドに関するいくつかのヘルプ

検索は、次で示される現在のディレクトリで検索を実行します .

-name 私の場合、ファイルの名前はpom.xmlでワイルドカードを指定できます。

-exec 実行する

sed ストリームエディター

-i 大文字小文字を区別しない

s 代用です

/4.6.0.../ 検索する文字列

/5.0.0.../ 置き換える文字列


おそらくそれほど強力ではないかもしれませんが、これは受け入れられた回答よりも理解するのがはるかに簡単です
icc97

5

私は私のために仕事に、このページ上のコマンドのいずれかを取得できませんでした:SEDソリューションは、それが処理されるすべてのファイルの末尾に改行を追加し、perlのソリューションは、検索からの十分な引数を受け入れることができませんでした。私は完全に機能するこの解決策を見つけました:

find . -type f -name '*.[hm]' -print0 
    | xargs -0 perl -pi -e 's/search_regex/replacement_string/g'

これにより、現在のディレクトリツリーが再帰的に検索され、末尾がまたはのファイルで置き換えsearch_regexられreplacement_stringます。.h.m

私は過去にこの目的でrplも使用しました。


0

forループを使用して何かを試してください

 for i in `egrep -lR "YOURSEARCH" .` ; do echo  $i; sed 's/f/k/' <$i >/tmp/`basename $i`; mv /tmp/`basename $i` $i; done

かなりではありませんが、すべきです。


3
ここではxargsの方が明らかに適切です。
Nathan Fellman、

1
また、|while read iパターンを使用すると、ストリーミングが可能になり、egrepの結果が長くなりすぎたときに長さの制限を回避できます
David Schmitt

0

私のユースケースは 、次のコードで置き換えたいと思っていましfoo:/Drive_Letterfoo:/bar/baz/xyz。私のケースでは、次のコードで置き換える ことができました。大量のファイルがあるのと同じディレクトリの場所にいた。

find . -name "*.library" -print0 | xargs -0 sed -i '' -e 's/foo:\/Drive_Letter:/foo:\/bar\/baz\/xyz/g'

お役に立てば幸いです。

更新s | foo:/ Drive_letter:| foo:/ ba / baz / xyz | g


:あなたはsedコマンドのために他の区切り文字を使用し、そうすることが非常に良くパス名を作ることができますsed 's|foo:/Drive_letter:|foo:/ba/baz/xyz|g'
ケビン
弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.