Obtendo as últimas linhas que correspondem a um padrão em vários arquivos

4

Eu tenho um aplicativo que gera um conjunto de arquivos de log para um diretório central como este:

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

Dentro de cada arquivo, diferentes medidas são tomadas durante o tempo de vida do processo de cada log, então as linhas são assim:

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

Estou com dificuldades para escrever alguns comandos que podem processar todos os arquivos e gerar a leitura ÚLTIMA de uma propriedade de doação, idealmente produzindo algo assim:

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

Alguma sugestão? Comecei a usar uma combinação de grep , cut , sort , uniq assim:

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

mas funcionou apenas parcialmente, pois em alguns experimentos acabaria imprimindo vários registros do mesmo log e excluindo alguns outros registros.

Eu segui para awk com isso:

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

e tive o problema que quando eu passar vários arquivos de entrada, só me dá a última linha do último arquivo de log em vez de 1 linha de saída por arquivo de log.

Alguma sugestão sobre como realizar isso?

    
por Dash83 31.07.2018 / 13:19

2 respostas

7

Dê uma olhada em ENDFILE blocks (GNU awk specific). Você poderia executar algo nos moldes de

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

Com GNU's grep & sed , você pode fazer isso da seguinte maneira:

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

Explicação:

  • A opção -z torna grep tratar o arquivo como uma cadeia longa, delimitada por -r .
  • A opção grep tornará -P recursiva
  • A opção Perl ativa o sabor -o regex.
  • A opção -h selecionará a parte correspondente.
  • A opção %code% irá suprimir a impressão de nomes de arquivos.
por 31.07.2018 / 15:50