Extrai uma ocorrência de um padrão do arquivo

1

Eu tenho arquivos grandes contendo registros semelhantes aos mostrados abaixo. Eu gostaria de encontrar todas as transações (TR #) que foram afetadas com o erro. Eu preciso extrair uma ocorrência de cada TR # ID.

Como eu poderia fazer isso?

    Apr 30 16:51:29.574 application.crit: [6104]:TR#14. Transaction send can not be sent. Error Code: 704
    Apr 30 16:51:29.574 application.crit: [6104]:TR#14. Transaction send can not be sent. Error Code: 704
    Apr 30 16:51:29.574 application.crit: [6104]:TR#14. Transaction send can not be sent. Error Code: 704
    Apr 30 16:51:29.574 application.crit: [6104]:TR#14. Transaction send can not be sent. Error Code: 704
    Apr 30 16:51:29.574 application.crit: [6104]:TR#238. Transaction send can not be sent. Error Code: 704
    Apr 30 16:51:29.574 application.crit: [6104]:TR#238. Transaction send can not be sent. Error Code: 704
    Apr 30 16:51:29.574 application.crit: [6104]:TR#238. Transaction send can not be sent. Error Code: 704
    Apr 30 16:51:29.574 application.crit: [6104]:TR#238. Transaction send can not be sent. Error Code: 704
    Apr 30 16:51:29.574 application.crit: [6104]:TR#238. Transaction send can not be sent. Error Code: 704
    Apr 30 16:51:29.574 application.crit: [6104]:TR#238. Transaction send can not be sent. Error Code: 704

Resultado exigido:

    Apr 30 16:51:29.574 application.crit: [6104]:TR#14. Transaction send can not be sent. Error Code: 704
    Apr 30 16:51:29.574 application.crit: [6104]:TR#238. Transaction send can not be sent. Error Code: 704
    
por Prabhu 13.05.2014 / 11:42

5 respostas

3

Isso é muito simples de fazer em awk :

$ awk 'c[$5]++==1' file 
Apr 30 16:51:29.574 application.crit: [6104]:TR#14. Transaction send can not be sent. Error Code: 704
Apr 30 16:51:29.574 application.crit: [6104]:TR#238. Transaction send can not be sent. Error Code: 704

Ou, em Perl:

$ perl -ane '$k{$F[4]}++==1 && print' file 
Apr 30 16:51:29.574 application.crit: [6104]:TR#14. Transaction send can not be sent. Error Code: 704
Apr 30 16:51:29.574 application.crit: [6104]:TR#238. Transaction send can not be sent. Error Code: 704

Os itens acima assumem que o número antes de cada TR#ID é parte do ID. Se os números podem mudar, mas você só precisa de um deles, use isso:

$ awk -F'[:.]' 'c[$7]++==1' file 

ou

$ perl -F'[:.]' -ane '$k{$F[6]}++==1 && print' file 
    
por 13.05.2014 / 16:11
3

Para obter e imprimir a primeira ocorrência de cada mensagem, tente

awk '! m[$5] {m[$5]=$0} END{for (e in m) print m[e]}'

Eu fiz os timestamps em seu exemplo seqüencial para testá-lo (e também corrigi o valor de erro final truncado):

$ awk '! m[$5] {m[$5]=$0} END{for (e in m) print m[e]}' tr2.log
Apr 30 16:51:27.574 application.crit: [6104]:TR#14. Transaction send can not be sent. Error Code: 704
Apr 30 16:51:31.574 application.crit: [6104]:TR#238. Transaction send can not be sent. Error Code: 704

Com agradecimentos ao @terdon

    
por 13.05.2014 / 12:33
2

Aqui está um script perl que faz o que você quer:

#!/usr/bin/perl

#Read each line
while ($line = <>) {
  # Extract the transaction ID by looking for the text TR followed by digits
  ($trid) = $line =~ /.*(TR#\d+).*/ ;
  # If we've not seen the ID before, print it out
  unless ($trids{$trid}) {
    print $line;
  }
  # Remember the ID so we don't print it out again
  $trids{$trid} = 1;
}

Quando eu chamo usando sua entrada, é isso que eu recebo:

temeraire:ul jenny$ ./extract.pl in.txt 
    Apr 30 16:51:29.574 application.crit: [6104]:TR#14. Transaction send can not be sent. Error Code: 704
    Apr 30 16:51:29.574 application.crit: [6104]:TR#238. Transaction send can not be sent. Error Code: 704
    
por 13.05.2014 / 12:09
2

Eu faria isso por meio de tarefas fáceis de realizar:

grep 'Error Code: 704' test_log | uniq | less

O comando grep selecionará apenas as linhas que contenham a string "Error Code: 704". O comando uniq manterá apenas um de cada elemento. O sinal ">" irá usar a saída padrão e enviá-lo para o arquivo chamado "new_file"

Provavelmente existem maneiras melhores de fazer isso que eu ainda não conheço

    
por 13.05.2014 / 11:58
1

Através do GNU sed , roubado de esta resposta,

sed '$!N; /^\(.*\)\n$/!P; D' file
    
por 13.05.2014 / 16:43