web-dev-qa-db-ja.com

複数のファイル間で複数行のgrepを実行するにはどうすればよいですか?

複数のログファイルで発生する場所でこのパターンを取得しようとしています(注:これらのパターンはサイズ、つまりBlahの量が大きく異なる可能性があります):

   Found an txt File
    Blah
    Blah
    10019874
    Blah
    Blah
    Processed File   

このコマンドラインの使用:

 pcregrep -M 'Found an.*(\n|.)*10019874.*(\n|.)*Processed' log_*.txt

私の正規表現はチェックアウトします REGEX HERE

-Mマルチラインフラグ付きのpcregrepを使用しています。 'log_'で始まり '.txt'で終わるすべてのログファイルに記録されます。このコマンドを実行すると、「セグメンテーション違反」が返されます。

これを行うためのより簡単でより良い方法はありますか?

5
blarg

コメントで述べたように、投稿したコマンドは私のLMDE(pcregrepバージョン8.31 2012-07-06)で正常に機能します。ただし、正規表現は探している文字列の一部しか指定しないため、通常のgrepを使用してこれを行うこともできます。

grep -A 6 'Found an' log_*.txt | grep -C 3 10019874

-A 6は渡された文字列とそれに続く6行に一致する行を出力し、-C 3は3 周囲行を出力します。最終結果は、使用していたpcregrepアプローチとまったく同じです。


パターンの行数が異なる可能性がある場合は、セグメンテーション違反を説明できます。おそらく、一部のファイルでは、一致したセクションが長すぎて、メモリ不足エラーが発生します。それを回避する1つの方法は、少しスクリプトを作成することです。

Perl -ne '$c=1 if /Found an/; ## set $c to 1 if this line matches 'Found on'
          if($c){               ## If $c is defined and non-0
            Push @F,$_;         ## Add the current line to the @F array
            $c++ if /10019874/; ## Increment $c if this line matches '10019874'
            if(/Processed/){    ## If this line matches 'Processed'
                print "@F" if $c>1; ## Print the contents of @F if $c is >1
                @F=""; $c=0;         ## Empty @F, set $c to 0.
            }
           }' log_*.txt 

ワンライナーと同じもの:

Perl -ne '$c=1 if /Found an/; if($c){Push @F,$_; $c++ if /10019874/; if(/Processed/){print "@F" if $c>1; @F=""; $c=0;}}' log_*txt 
4
terdon