ログファイルがあり、bashスクリプトを介してデータを「grep」しようとしています。私が特に興味を持っているデータは、「ERR-」パターンを持ち、読みやすくするために各項目の後に空白行を含む2つのタイムスタンプ(親タイムスタンプを含む)の間のすべての行です。
サンプルログファイル:
Tue May 24 21:22:12 2022
ERR-0045 Lock detected in /tmp/file.lck
Tue May 24 21:44:12 2022
Errors in file /tmp/filename01.trc:
ERR-0001: Error detected. /tmp/filename.log
Tue May 24 21:47:25 2022
im some output
Tue May 24 21:47:25 2022
im some output too
im some output aswell
Tue May 24 21:48:03 2022
Errors in file /tmp/filename09.trc:
ERR-0100: error
ERR-0050: failure of sorts.
ERR-0052: line 3421
Tue May 24 21:49:07 2022
Completed process xyz
だから私が望む出力は次のようになります。
Tue May 24 21:22:12 2022
ERR-0045 Lock detected in /tmp/file.lck
Tue May 24 21:44:12 2022
Errors in file /tmp/filename01.trc:
ERR-0001: Error detected. /tmp/filename.log
Tue May 24 21:48:03 2022
Errors in file /tmp/filename09.trc:
ERR-0100: error
ERR-0050: failure of sorts.
ERR-0052: line 3421
私は大きな成功なしにsed / awk / catの組み合わせを試しました。私が問題がある場所は次のとおりです。
- ERRには常にタイムスタンプの前に2行は含まれていません。
- タイムスタンプブロックには複数のERRがあります。
- 日付は明らかに変更されるため、フォーマットは変更されませんが、ハードコーディングしたくありません。
事前にありがとう
ベストアンサー1
スクリプトtst.awk
:
function print_r() { if (e) print r; r = ""; e = 0 }
/^([[:alpha:]]{3} ){2}[[:digit:]]{1,2} [[:digit:]]{2}(:[[:digit:]]{2}){2} [[:digit:]]{4}$/ {
print_r()
}
/^ERR-/{ e = 1 }
{ r = r ORS $0 }
END{ print_r() }
使用法および出力:
$ awk -f tst.awk file
Tue May 24 21:22:12 2022
ERR-0045 Lock detected in /tmp/file.lck
Tue May 24 21:44:12 2022
Errors in file /tmp/filename01.trc:
ERR-0001: Error detected. /tmp/filename.log
Tue May 24 21:48:03 2022
Errors in file /tmp/filename09.trc:
ERR-0100: error
ERR-0050: failure of sorts.
ERR-0052: line 3421
独自の式を使用してタイムスタンプまたはエラーを示すことができます。これは、提示された形式に一致する行全体です(日付検証なし)。行の先頭に「ERR-」を追加します。
メモ:
r
エラーが見つかった場合は、レコード()を印刷する関数()を定義しますe
。これら2つの変数も印刷後にリセットする必要があります。の場合、awk
値で初期化されていない変数は空の文字列またはゼロと評価されます。日付の正規表現が一致したときにこの関数を呼び出します。古いロギングを完了し、新しい履歴の保存を開始します。履歴は複数行のログなので、印刷する必要があるかどうかはまだわかりません。
エラーパターンが一致する場合を設定します
e
。各行ごとに既存のレコードに行を追加し、
ORS
出力レコード区切り文字(デフォルトの改行)で区切ります。また、出力行間の空白行はの先頭に配置されますr
。r
ここで新しいタイムスタンプを取得すると、常に空の文字列になります。END
最後のレコードがまだ残っているので、関数をもう一度呼び出します。