awkは、パターン1の行にパターン2がある場合、パターン1の行と次のn番目の行が単一の行として印刷されます。

awkは、パターン1の行にパターン2がある場合、パターン1の行と次のn番目の行が単一の行として印刷されます。

現在、以下のログ出力があります。

20200124_075926.795633 [24_1859] [ERROR  ] [PID] error running program:
...
...
actual error message from n lines below
...
20200124_075929.261693 [24_1859] [INFO   ] [PID] blah
20200124_075929.374937 [24_1859] [PERF   ] [PID] blah blah
20200124_075930.660998 [24_1859] [ERROR  ] [PID] some error:
20200124_075956.793528 [24_1859] [ERROR  ] [PID] error running program:
...
...
actual error message from n lines below
...

私は現在、エラーと致命的なメッセージを含むログ行を出力し、タイムスタンプを含む最初の2つの列を削除するために次のように使用しています。

awk '/\[[FATAL|ERROR].*] \[.*\]/ { print substr($0, index($0,$3)) }' filename

これにより、私が望む正確な結果が生成されます(少なくとも発生回数の合計)。

[ERROR  ] [PID] error running program:
[ERROR  ] [PID] some error:
[ERROR  ] [PID] error running program:

それでは、上記のIFで一致する行のテキストを含めるように拡張したいと思います。この行には2番目のパターンが含まれています。

たとえば、最初のパターンの行に " error running program"も含まれている場合は、次のn行が含まれます。それ以外の場合は、行を印刷して続行します。

[ERROR  ] [PID] error running program: actual error message from n lines below
[ERROR  ] [PID] some error:
[ERROR  ] [PID] error running program: actual error message from n lines below

ベストアンサー1

$ cat tst.awk
{
    sub(/\r$/,"")
    txt = substr($0, index($0,$3))
}
/\[(FATAL|ERROR)[^]]*] \[.*]/ {
    if ( /error running program:/ ) {
        pfx = txt OFS
        cnt = 4
    }
    else {
        cnt = 1
    }
}
cnt && !--cnt { print pfx txt; pfx="" }

$ awk -f tst.awk file
[ERROR  ] [PID] error running program: message from n lines below
[ERROR  ] [PID] some error:
[ERROR  ] [PID] error running program: message from n lines below

おすすめ記事