Text-Processing

獲取與多個文件中的模式匹配的最後一行

  • July 31, 2018

我有一個將一組日誌文件輸出到中央目錄的應用程序,如下所示:

/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 個輸出行。

關於如何做到這一點的任何建議?

看一下ENDFILE塊(特定於 GNU awk)。你可以按照以下方式執行一些東西

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

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選項將禁止列印文件名。

引用自:https://unix.stackexchange.com/questions/459582