web-dev-qa-db-ja.com

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

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

/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=...

助言がありますか? grepcutsortuniqの組み合わせを次のように使い始めました。

$ 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つの出力行ではなく、最後のログファイルの最後の行しか表示されないという問題がありました。

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

4
Dash83

ENDFILEブロック(GNU awk固有)を見てください。あなたはの線に沿って何かを実行することができます

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

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

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

説明:

  • -zオプションを使用すると、grepはファイルを\0で区切られた1つの長い文字列として扱います。
  • -rオプションはgrepを再帰的にします
  • -Pオプションは、Perl正規表現フレーバーをオンにします。
  • -oオプションは、一致する部分を選択します。
  • -hオプションは、ファイル名の印刷を抑制します。
2
Rakesh Sharma