2016-03-27 1 views
1

は問題だ:私はそのファイルの数千がある参照I grep -rnwl 'C:\out\' --include=*.txt -E --file='comp.log'場合、または各パターンファイルに基づいてgrep + sedを使用しますか?ここ

を正規表現を含む300行のリスト内の文字列の一つ以上が含まれていない場合があります〜35Kのファイルを持っています一致が含まれています。

これまでに使用されていたcomp.logの文字列を含むこれらのファイルの各行を削除するにはどうすればよいですか?

編集:comp.logは各行の簡単な正規表現が含まれていますが、ほとんどの部分で一致する各文字列は、これがあるユニークな

あり、それが構成されている方法の例です:

server[0-9]\/files\/bobba fett.stw 
[a-z]+ mochaccino 
[2-9] CheeseCakes 
... 

など愚かな例を除いて、各行がいくつかのバリエーションのために独特のものであることを示していますので、本当に必要なものに影響を与えるべきではありません。インラインではなくファイル内のパターンを使いたいという点を除いて、 's/pattern/replacement /'と変わりはありません。


[OK]を、ここでMUCHフィッシャーアプローチ@/@ Kenavozをいじった後、私は完全に別の解決策を見つけましたが、更新(私は数日後に答えた質問を宣言しない場合はSO入院患者を取得します) です最初のものが最初に。 で動作するsed用の修正されたパターンリストを作成すると、が動作します。

と同様に、serを落と​​す@werkritterのアプローチです。 (この1つは私が見つけた最も多くの...間違って... "問題を回避する方法")。

で問題を解決してしまった私は(...それが何を意味するのかわからない。数字。それはUbuntuの下で動作しなかったので)

窓/ cygwinの下Mklementの答えの仕事@作ることができませんでした

もっと...長期的には、再利用可能なフォームは、PowerGrepと呼ばれる教授によって指摘されたすばらしいプログラムでした。それは本当に他のすべてのオプションを水から吹き飛ばします。残念ながらそれは窓だけであり、無料ではありません。 (ここで広告することさえ、物事は安くはないが問題を解決する)。

@ werkiterの回答は「適切な」回答ではなく、解決策として@Lars Fischerと@ Kenavozの回答を選択するだけではありません(彼らはお互いを補完します)、私は@Kenavozに最初。

最終的な考え:私はより単純で普遍的で無料のソリューションを望んでいましたが、明らかにそうではありません。

+1

は何である ' 'Cと: \ out \ ''?あなたはWindows/DOSマシンですか? – anubhava

+0

か、パターンファイルと比較するのではなく、grepからファイルパスと行番号を渡すことができますか? – VileTouch

+0

はい、それはウィンドウですが、cmdの代わりにminttyを開くと、それは異なって見えるので、関連性はないと思います。 "c:\ out"は、変更するすべてのファイルが存在するパスです。 – VileTouch

答えて

2

あなたはこれを試すことができます。

sed -f <(sed 's/^/\//g;s/$/\/d/g' comp.log) file > outputfile 

comp.logのすべての正規表現はdコマンドを使用して、sedのアドレスにフォーマットされています:/regex/d。このコマンドは、パターンに一致する行を削除します。

この内部SEDはfileに適用sedの外部の-fオプションに(process substititionで)ファイルとして送信されます。更新

sed -f <(sed 's/^/s\//g;s/$/\/\/g/g' comp.log) file > outputfile 

コマンドの出力がoutputfileにリダイレクトされたパターン(すべてではない行)を合わせるだけで文字列を削除するには

+0

私が正しく理解していれば、あなたの出力ファイルはcomp.log です;それは編集したいファイルではありません;ファイル内で一致する文字列のリストは、あなたの正規表現です。 しかし、sedの中でsedを使って、... 1行を含む一時ファイルを出力したようです。 – VileTouch

+0

更新されました。内部sedは正規表現ファイルをsed形式のパターンに変換します。プロセス置換では、 'file'に適用される正規表現ファイルとして使用されます。 – SLePort

2

いくつかのアイデアがありますが、完全な解決策ではありません。あなたのスクリプト(質問には表示されていません)に採用する必要があります。

  1. 私は必要な削除含むsedスクリプトにcomp.logを変換します:

    cat comp.log | sed -r "s+(.*)+/\1/ d;+" > comp.sed` 
    

    あなたの例は次のようになりcomp.sedになるだろう:私はその後、

    /server[0-9]\/files\/bobba fett.stw/ d; 
    /[a-z]+ mochaccino/ d; 
    /[2-9] CheeseCakes/ d; 
    
  2. をgrepによって報告された各ファイルにcomp.sedスクリプトを適用します(-rnwlでファイル名を取得するためにフィルタリングが必要です)。

    sed -i.bak -f comp.sed $AFileReportedByGrep 
    

    あなたがGNUのsedを持っている場合は、あなたがそうでなければ

+0

これは '' cat'の無用な使い方ですが(http://www.iki.fi/era/unix/award.html)、一般的には良いコメントです。 – tripleee

+0

あなたの文章を書く前に私の答えをお読みになりましたか? – SLePort

+0

まあ、スクリプトはありません。私はforループで.batファイルを使い始めましたが、grepのほうが遅すぎて効率が悪いので、そこにはすべてがあります。 はい、私のsedは-iパラメータを受け入れます。私はcygwinに付属していると思います。 – VileTouch

0

両方Kenavoz's answerLars Fischer's answer同じ独創的なアプローチで使用し、一時ファイルに配管を使用し、.BAKのバックアップを作成する-iインプレースの交換を使用することができます。
を入力正規表現のリストをsedの一致と削除コマンドのリストに変換し、-fを介してsedへのスクリプトとして動作するファイルとして渡します。

find 'c:/out' -name '*.txt' -exec sed -i -r -f <(sed 's#.*#/\\<&\\>/d#' comp.log) {} + 
  • :あなたはGNUsedを持っており、あなたのシェルが(<(...)をサポートするため)bashksh、またはzshであると仮定すると、一緒にそれをすべてを置く単一のコマンドでこれらの答えを補完するために

    find 'c:/out' -name '*.txt'は、dirのサブツリー内のすべてのファイル*.txtと一致します。 c:/out

    • -exec ... +通常のみ単一の呼び出しで、その結果、指定されたコマンドに単一コマンドラインに収まる限り多くの一致するファイルを渡します。
  • sed -iインプレース入力ファイルは、(概念的に話す - 注意点があります)を更新します。接尾辞(たとえば、-i.bak)を追加して、その接尾辞付きの元のファイルのバックアップを保存します。

  • sed -r拡張の入力正規表現がサポートされています。

  • sed -fKenavoz's answerで説明したように、この場合は、指定されたファイル名から実行するスクリプトは、[トランジェント]のファイルのように囲まれsedコマンドの出力行為を行うために、プロセス置換(<(...))を使用しています読み込みます。

    • s///sedコマンド - リテラル/の使用を容易にするために、別のデリミタ#を使用 - 所望の削除コマンドを生成する/\<...\>/dcomp.logから各ラインを囲みます。入力正規表現を\<...\>で囲むと、という単語として一致することが保証されます(grep -w)。 POSIXのERE(拡張正規表現)やBSD/OSX sedサポート\<\>でもないので、
      この主な理由は、なぜGNUsedが、必要とされます。
      • ただし、-E-rを交換することによって、それはBSD/OSX sedで動作させることができ、かつ\</\>[[:<:]]/[[:>:]]
関連する問題