次のように、ログファイルセットを中央ディレクトリに出力するアプリケーションがあります。
/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
ました。sort
uniq
$ 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
繰り返されます-P
Perl
オプションは正規表現スタイルを有効にします。-o
オプションは一致する部品を選択します。-h
オプションはファイル名の印刷を抑制します。