Um script de shell para gravar campos selecionados em uma única linha

5

Eu tenho um arquivo de log trace.log que imprime o registro de data e hora, o nome do segmento, o método de transação e o ID da transação, conforme abaixo.

2014-01-23 15:50:41,724 [catalina-exec-35] INFO  TRANSACTION getConnection REQUEST, ID=1308::
2014-01-23 15:50:41,725 [catalina-exec-33] INFO  TRANSACTION getConnection REQUEST, ID=1304::
2014-01-23 15:50:41,727 [catalina-exec-10] INFO  TRANSACTION getConnection REQUEST, ID=1298::
2014-01-23 15:50:41,727 [catalina-exec-24] INFO  TRANSACTION getConnection REQUEST, ID=1307::
2014-01-23 15:50:41,727 [catalina-exec-12] INFO  TRANSACTION getConnection DONE, ID=1305::
2014-01-23 15:50:41,733 [catalina-exec-10] INFO  TRANSACTION getConnection DONE, ID=1298::
2014-01-23 15:50:41,734 [catalina-exec-26] INFO  TRANSACTION getConnection REQUEST, ID=1313::
2014-01-23 15:50:41,734 [catalina-exec-26] INFO  TRANSACTION getConnection DONE, ID=1313::
2014-01-23 15:50:41,738 [catalina-exec-39] INFO  TRANSACTION getConnection REQUEST, ID=1311::
2014-01-23 15:50:41,733 [catalina-exec-35] INFO  TRANSACTION getConnection DONE, ID=1308::
2014-01-23 15:50:41,738 [catalina-exec-27] INFO  TRANSACTION getConnection REQUEST, ID=1309::
2014-01-23 15:50:41,737 [catalina-exec-22] INFO  TRANSACTION getConnection REQUEST, ID=1310::
2014-01-23 15:50:41,743 [catalina-exec-30] INFO  TRANSACTION getConnection REQUEST, ID=1315::
2014-01-23 15:50:41,744 [catalina-exec-39] INFO  TRANSACTION getConnection DONE, ID=1311::
2014-01-23 15:50:41,747 [catalina-exec-2] INFO  TRANSACTION getConnection REQUEST, ID=1318::

Eu quero grep e imprimo a data e hora de getConnection REQUEST e getConnection DONE para uma ID específica em uma única linha em um arquivo.

Eu escrevi um script de shell que imprime o registro de data e hora em várias linhas, conforme abaixo. Aqui está o meu script de shell

for i in {1..800}
do
     echo "Welcome $i times"
     echo "ID=$i, getConnection " >> time.log
     grep ID=$i: trace.log | grep getConnection | cut -d'[' -s -f1 >> time.log
echo "      " >> time.log
done

A saída é como mostrado abaixo

ID=791, getConnection
2014-01-23 15:50:16,703
2014-01-23 15:50:16,706

ID=792, getConnection
2014-01-23 15:50:16,704
2014-01-23 15:50:16,704

ID=793, getConnection
2014-01-23 15:50:16,704
2014-01-23 15:50:16,709

ID=794, getConnection
2014-01-23 15:50:16,708
2014-01-23 15:50:16,712

Como posso mudar isso? Eu preciso de saída como mostrado abaixo:

ID=792, getConnection 2014-01-23 15:50:16,703 2014-01-23 15:50:16,706

ID=792, getConnection 2014-01-23 15:50:16,704 2014-01-23 15:50:16,704

ID=793, getConnection 2014-01-23 15:50:16,704 2014-01-23 15:50:16,709

ID=794, getConnection 2014-01-23 15:50:16,708 2014-01-23 15:50:16,712
    
por hs.chandra 23.01.2014 / 13:27

5 respostas

6

Não use loops de shell para processar texto, isso é uma prática ruim.

O trabalho do shell é executar comandos (os corretos) e fazê-los cooperar em uma tarefa.

Aqui, o comando correto é o interpretador de linguagem de extração e relatório prático chamado uma vez, não vários comandos executados (em seqüência!) para cada linha de um arquivo.

perl -lne '
  if (/(.*?) \[.*getConnection (.*?), (ID=\d+)/) {
    if ($2 eq "REQUEST") {$r{$3}=$1}
    elsif ($2 eq "DONE") {print "$3, getConnection $r{$3} $1" if $r{$3}}
  }' < your-file
    
por 23.01.2014 / 15:16
1

você pode suprimir a nova linha passando o sinal -n para echo .

para que o seguinte funcione

for i in {1..800}
do
     echo "Welcome $i times" 1>&2
     echo -n "ID=$i, getConnection "
     grep "ID=${i}:" trace.log \
     | grep getConnection      \
     | cut -d'[' -s -f1        \
     | while read line
     do
       echo -n "    ${line}"
     done
     echo
done  >> time.log
    
por 23.01.2014 / 13:40
1

Você está muito perto:

for i in {1..800}
do
     echo "Welcome $i times"
     echo -n "ID=$i, getConnection " >> time.log
     grep ID=$i: trace.log | grep getConnection | cut -d'[' -s -f1 | xargs >> time.log
     echo "      " >> time.log
done

echo -n garante que você não inclua uma nova linha, o xargs (ação padrão echo ) combina a entrada de múltiplas linhas aos argumentos.

Dessa forma, você tem a linha extra com espaço em branco, conforme especificado na sua pergunta.

    
por 23.01.2014 / 13:58
0

Rápido e sujo:

# cat file
ID=791, getConnection
2014-01-23 15:50:16,703
2014-01-23 15:50:16,706
[...]

# cat file | tr '\n' ';' | sed "s/;;/\n/g" | sed "s/;/ /g"
ID=791, getConnection    2014-01-23 15:50:16,703    2014-01-23 15:50:16,706
ID=792, getConnection    2014-01-23 15:50:16,704    2014-01-23 15:50:16,704
ID=793, getConnection    2014-01-23 15:50:16,704    2014-01-23 15:50:16,709
ID=794, getConnection    2014-01-23 15:50:16,708    2014-01-23 15:50:16,712

link

    
por 23.01.2014 / 13:41
0

não shell, mas perl você pode gostar:

#!/usr/bin/perl -n

s{([^,]+,\d+) .*? getConnection (REQUEST|DONE), (ID=\d+)::}{$h{$3}{$2} = $1}e; 

END { 
    for (sort keys %h) {
        printf "%s, getConnection %24s %24s\n",
           $_, $h{$_}{REQUEST},$h{$_}{DONE};
    }
}    

saída:

perl checkerbunny < data
ID=1298, getConnection  2014-01-23 15:50:41,727  2014-01-23 15:50:41,733
ID=1304, getConnection  2014-01-23 15:50:41,725                         
ID=1305, getConnection                           2014-01-23 15:50:41,727
ID=1307, getConnection  2014-01-23 15:50:41,727                         
ID=1308, getConnection  2014-01-23 15:50:41,724  2014-01-23 15:50:41,733
ID=1309, getConnection  2014-01-23 15:50:41,738                         
ID=1310, getConnection  2014-01-23 15:50:41,737                         
ID=1311, getConnection  2014-01-23 15:50:41,738  2014-01-23 15:50:41,744
ID=1313, getConnection  2014-01-23 15:50:41,734  2014-01-23 15:50:41,734
ID=1315, getConnection  2014-01-23 15:50:41,743                         
ID=1318, getConnection  2014-01-23 15:50:41,747                         

    
por 23.01.2014 / 18:18