複数のファイルのパターンに一致する最後の数行を取得します。

複数のファイルのパターンに一致する最後の数行を取得します。

次のように、ログファイルセットを中央ディレクトリに出力するアプリケーションがあります。

/tmp/experiment/log/    
├── node01.log
├── node02.log
├── node03.log
├── node04.log
├── node05.log
├── node06.log

各ファイル内では、各ログプロセスの存続期間中にさまざまな操作が実行されるため、対応する行は次のようになります。

prop1=5, ts=X, node01
prop2=3, ts=X, node01
prop1=7, ts=Y, node01
...

すべてのファイルを処理し、特定の属性の最後の読み取りを出力するいくつかのコマンドを作成しようとしています。理想的には、出力は次のようになります。

node01, prop1=7, ts=...
node02, prop1=9, ts=...
node03, prop1=3, ts=...

どんな提案がありますか?私は次のように、の組み合わせを使用grepし始めcutました。sortuniq

$ grep -sirh "prop1" /tmp/experiment/log/ | \
   cut --delimiter=, --fields=1,4 | uniq | sort | \
   tail -n 14`  --this example had 14 log files

ただし、一部の実験では、同じログ内の複数のレコードを印刷し、いくつかの異なるログを除外するため、部分的にのみ機能します。

私は続けましたawk

$ awk -F":" '/prop1/ { print $NF $2}' /tmp/experiment/log/node*.log | \
   awk 'END { print }'

また、複数の入力ファイルを渡すと、ログファイルごとに1つの出力行ではなく、最後のログファイルの最後の行だけが提供されるという問題があります。

これを達成する方法について提案がありますか?

答え1

ENDFILEブロック(GNU固有)を見てくださいawk。次のように何かを実行できます

awk     'BEGINFILE { a = ""}
         /prop1/   { a=$NF $2 $1}    ## Change this if necessary
         ENDFILE   { if (a != "") print FILENAME, a}' ./node*.log

答え2

GNU's grep & sed次のようにこれを行うことができます。

grep -zoPhr '(.*\n)+\Kprop1=[^\n]*' /tmp/experiment/log/ | sed 's/\(.*\),\s\(.*\)/\2, \1/'

説明する:

  • -zオプションを使用すると、grepファイルが\0
  • -rオプションがgrep繰り返されます
  • -PPerlオプションは正規表現スタイルを有効にします。
  • -oオプションは一致する部品を選択します。
  • -hオプションはファイル名の印刷を抑制します。

関連情報