2017-09-14 5 views
2

背景

私は、特定のパターンに一致する行で始まるログを追跡するためにsedをたくさん使用します。その例として、このログ行のために..私は(私の識別子は、注文番号とスレッド番号です後にそれらを使用してフィルタリングすることができるように、私は単純に先頭に追加識別子を持つ行をログコードでsedを複数行のパターンにマッチさせる方法

sed -ne '/pattern/ p' infile >outfile 

:私は、このコマンドを使用します。 (私は7123を注文する関連するすべてのログをフィルタリングしていた場合)

9/14/2017 10:19:58 AM::: ORD7123::TH41361::Failed Checkout 

は順序7123スレッド41361.のために上記だから、sedコマンドで次のようになります。

sed -ne '/ORD7123/ p' infile >outfile 

問題

シングルオーダー/スレッドの組み合わせのログがそうのような複数行にわたる場合、問題が起こる:

9/14/2017 10:19:58 AM::: ORD7123::TH41361::Failed Checking Out With Credit Card for # 3 times. Error: { 
    "order": "country is required", 
    "credit_card": "year is not a valid year" 
}. 
9/14/2017 10:19:59 AM::: ORD7123::TH41347::Successfully Got a something Solution 

上記のsedコマンドを使用しては、私の出力は、この

9/14/2017 10:19:58 AM::: ORD7123::TH41361::Failed Checking Out With Credit Card for # 3 times. Error: { 
9/14/2017 10:19:59 AM::: ORD7123::TH41347::Successfully Got a something Solution 
のようになります。

提案/分析

私たちは(ログの作成を管理していた)以前にこの問題に直面していました。対処方法は、新しい行を/nなど。この場合、私は、ログの作成に対し多くのコントロールを持っていない、と

+0

これは役に立ちますか? http://www.grymoire.com/Unix/Sed.html#toc-uh-51 – Jerinaw

答えて

1

awkが道にlogstash作品を仕事とのメッセージをログ収集できるよう、これを処理することができるはずであるように、私は、ログに対処しなければなりません複数の行。あなたの例を見ると、複数の行にまたがる{ ... }の間にテキストをキャプチャするように見えます。したがって、あなたが何かのリンクを使用することができ、この:

awk '/ORD7123/ {p=NR} NR==p+1 {p = (/^[0-9]{1,2}\/[0-9]{1,2}\/[0-9]{4}/? 0 : NR)} p' file 

9/14/2017 10:19:58 AM::: ORD7123::TH41361::Failed Checking Out With Credit Card for # 3 times. Error: { 
    "order": "country is required", 
    "credit_card": "year is not a valid year" 
}. 
9/14/2017 10:19:59 AM::: ORD7123::TH41347::Successfully Got a something Solution 

このawkコマンドルックス:例ログに示すように、あなたは常に{ ... }を持っていない場合は

awk '/ORD7123/{if (/{$/) p=1; print; next} p; p && /^}/{p=0}' file.log 

あなたは、このawkコマンドを使用することができますすべてのログ行で日付パターンを開始し、それが見つからない場合は前のログメッセージの続きとみなされます。

+0

これは、ログメッセージに常に{{}}があるかどうかをOPから知りたいことです。 – anubhava

1

awkのソリューション:

awk -v p="ORD7123" '$0~p{ print; 
      while(getline nl > 0 && (nl!~/^[0-9]+\/[0-9]{2}/ || nl~p)){ 
       print nl 
      } 
     }' inputfile 

出力例:

9/14/2017 10:19:58 AM::: ORD7123::TH41361::Failed Checking Out With Credit Card for # 3 times. Error: { 
    "order": "country is required", 
    "credit_card": "year is not a valid year" 
}. 
9/14/2017 10:19:59 AM::: ORD7123::TH41347::Successfully Got a something Solution 
0

これはあなたのために働くかもしれない(GNUのSED):

sed ':a;/ORD7123/!d;:b;n;/^..\?\/..\?\/.... ..:..:.. /ba;bb' file 

マッチに必要な文字列に( ORD7123)それ以外の場合は、行を削除します。一致した場合は、後続の行を日付と時刻で始まる行まで読み取って印刷し、必要な文字列を確認します。

0

sedは、個々の行での単純な置換の場合、です。すべてです。個々の行で簡単な置換をしようとしていないので、sedを考慮する必要はありません。あなただけOFSORSを変更することにより、単純な(またはあなたが好む他の文字列であることをさらに処理したい場合、非常に簡単にレコードの途中で改行を削除するために微調整することができます

$ cat tst.awk 
/^[0-9]/ { prt() } 
{ rec = (rec=="" ? "" : rec ORS) $0 } 
END { prt() } 
function prt() { 
    if (rec ~ /ORD7123/) { 
     print rec 
    } 
    rec = "" 
} 

$ awk -f tst.awk file 
9/14/2017 10:19:58 AM::: ORD7123::TH41361::Failed Checking Out With Credit Card for # 3 times. Error: { 
    "order": "country is required", 
    "credit_card": "year is not a valid year" 
}. 
9/14/2017 10:19:59 AM::: ORD7123::TH41347::Successfully Got a something Solution 

:ただのawkを使用)レコードがコンパイルされている場所:

$ cat tst.awk 
/^[0-9]/ { prt() } 
{ rec = (rec=="" ? "" : rec OFS) $0 } 
END { prt() } 
function prt() { 
    if (rec ~ /ORD7123/) { 
     print rec 
    } 
    rec = "" 
} 

$ awk -f tst.awk file 
9/14/2017 10:19:58 AM::: ORD7123::TH41361::Failed Checking Out With Credit Card for # 3 times. Error: { "order": "country is required", "credit_card": "year is not a valid year" }. 
9/14/2017 10:19:59 AM::: ORD7123::TH41347::Successfully Got a something Solution 
関連する問題