web-dev-qa-db-ja.com

sedおよびgrep / egrepを使用して検索および置換する

egrep -Rに続いて、約10個のユニオンを含む正規表現を使用しています。たとえば、.jpg | .png | .gifなどです。これはうまく機能し、見つかったすべての文字列を.bmp

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

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

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

95
Ori

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

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"".jpg"".gif"、または".png"のいずれかの文字列に一致

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

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

    • -0\0をレコード区切り文字として使用します。これは、egrep-Zと一致し、入力ファイル名のスペースや改行にだまされないようにするために重要です。

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

  • seds tream ed itor

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

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

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

180
David Schmitt

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

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

sed(可能であれば)またはawkでの複雑な作業ではなく...

11
Alex Martelli

これを行う別の方法

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.../置換される文字列

9
Cyril Cherian

このページでコマンドを実行できませんでした: sed solution は、処理したすべてのファイルの末尾に改行を追加し、 Perl solution = findから十分な引数を受け取ることができませんでした。私は完璧に機能するこのソリューションを見つけました:

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

これは、現在のディレクトリツリーを再帰的にたどり、search_regexまたはreplacement_stringで終わるファイルの.h.mに置き換えます。

また、過去にこの目的で rpl を使用しました。

5
titaniumdecoy

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

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

お役に立てば幸いです。

UPDATE s | foo:/ Drive_letter:| foo:/ ba/baz/xyz | g

0
neo7

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

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

きれいではありませんが、そうすべきです。

0
Don Johe