2行間のデータを抽出するコマンド

2行間のデータを抽出するコマンド

ログ ファイルの行番号から始まる例外と対応するスタック トレースを抽出する必要があります。エラーの開始行番号はわかっています。以下の例からスタック トレースが終了する場所を見つけるにはどうすればよいでしょうか。ご協力をお願いいたします。


-------
2016-10-07 15:49:07,537 エラー 例外が発生しました
 スタックトレースの行 1
 スタックトレースの2行目
 スタックトレース行 n
2016-10-07 15:49:07,539 デバッグ何とか何とか
2016-10-07 15:49:07,540 デバッグ何とか何とか

答え1

要約すると、指定した行番号から始まり、日付で始まる最初の行の直前まで続く行を印刷したいということです。この例では、開始行は 3 です。その場合、次のようになります。

$ awk '{if (NR==3)f=1; else if (/^[0-9-]{10} /)f=0} f{print}' trace.log
2016-10-07 15:49:07,537 ERROR Some exception
 stacktrace line 1
 stacktrace line 2
 .
 .
 stacktrace line n

上記のコードは次のように動作します。

  • if (NR==3)f=1

    指定した行番号で、変数をf1 に設定します。

  • else if (/^[0-9-]{10} /)f=0

    その他の行では、f行が 10 文字の数字またはダッシュとそれに続くスペースで始まる場合は 0 に設定します。つまり、f日付のように見えるもので始まる最初の行では 0 に設定します。

    必要に応じて、より複雑な正規表現を使用して日付の開始を識別することができます。たとえば、次の行では、行の先頭がデータのようなもので始まり、その後にスペース、その後に時間のようなもの、最後にカンマが続く必要があります。

    awk '{if (NR==3)f=1; else if (/^[0-9-]{10} [0-9:]{8},/)f=0} f{print}' trace.log
    

    これにさらなる改善を加えることも可能です。

  • f{print}

    がゼロ以外の場合はf、行を出力します。

    f{print}簡潔にするために、を に置き換えることもできますf。これが可能なのは、アクションが明示的に指定されていない場合、 のデフォルトアクションprintが使用されるためです。

代替

awk の一部のバージョンでは、 のような繰り返し要素がサポートされていません{10}。その場合は、次を試してください。

awk '{if (NR==3)f=1; else if (/^[0-9][0-9][0-9][0-9]-[0-9][0-9]-[0-9][0-9] /)f=0} f{print}' trace.log

答え2

すべてのスタック トレースの行が空白 (スペース/タブ) で始まると仮定すると、[[:blank:]]行の先頭 ( ) でそれらを一致させることができます^

grep '^[[:blank:]]' file.log

答え3

抽出したいトレースが の2行目から始まりtrace.log、その終わりがYYYY-MM-DD形式の日付で始まる行で示されている場合(そしてトレースにそのような行がない場合)、

sed -nE '2,/^[0-9]{4}-[0-9]{2}-[0-9]{2} /p' trace.log

2行目からすべての行を印刷しますを通してライン+3 (トレースの後の最初の行で、日付で始まる行)。最後の行は不要なので、上記を最後の行を削除するコマンドにパイプします。

sed -nE '2,/^[0-9]{4}-[0-9]{2}-[0-9]{2} /p' trace.log | head -n -1

または

sed -nE '2,/^[0-9]{4}-[0-9]{2}-[0-9]{2} /p' trace.log | sed '$d'

デート相手を探す必要がある場合そして時間を検索し、

^[0-9]{4}-[0-9]{2}-[0-9]{2} [0-9]{2}:[0-9]{2}:[0-9]{2}

関連情報