Como grep / awk / sed para texto em um log e exibir o pedaço que tem o texto?

1

Estou procurando algo muito semelhante a isso .

Os registros são assim:

[09:44:22] [main] ERROR [url/location] - A ONE LINE ERROR
[09:44:22] [main] ERROR [url/location] - Another ERROR 
[09:44:22] [main] SOMETHING DIFFERENT
[09:44:22] [main] SOMETHING DIFFERENT AGAIN
[09:44:22] [main] WARN [url/location] - ANOTHER ONE LINE WARN

Linha após linha, sem linhas vazias entre elas, embora, ocasionalmente, haja recuos quando informações adicionais estão disponíveis para uma peça específica.

Eu quero ser capaz de extrair todas as linhas que incluam ERROR (idealmente como um script que possa extrair ERROR E / Ou FAIL , WARN etc.) e exibi-las de acordo com um parâmetro. Vai fazer peneirar os logs em busca de falhas e muito mais fácil.

    
por Patremagne 14.07.2016 / 17:29

3 respostas

1

Suponho que o seu arquivo de log é assim?

example.log:

[09:44:22] [main] ERROR [url/location] - A ONE LINE ERROR
[09:44:22] [main] ERROR [url/location] - A MULTI LINE ERROR 
    with whitepace indention
[09:44:22] [main] ERROR [url/location] - A MULTI LINE ERROR 
       with tab indention
[09:44:22] [main] SOMETHING DIFFERENT
[09:44:22] [main] SOMETHING DIFFERENT
       with tab indention
[09:44:22] [main] WARN [url/location] - ANOTHER ONE LINE WARN

É certo que não é um de uma linha e perl, mas deve fazer o trabalho:

logsifter.pl:

#!/usr/bin/perl
use warnings;
use strict;

my $buffer="";

while(my $line= <>){
  chomp $line;
  if($line=~/ERROR|INFO|WARN/){
    print "$buffer\n" if $buffer;
    $buffer = $line;
  }
  elsif($line=~/^\s+(.*)$/){
    $buffer .= $1 if $buffer;
  }
  else{
    if($buffer){
      print "$buffer\n";
      $buffer ="";
    }
  }
}

print "$buffer\n";

chame como:

perl logsifter.pl < example.log
 [09:44:22] [main] ERROR [url/location] - A ONE LINE ERROR
 [09:44:22] [main] ERROR [url/location] - A MULTI LINE ERROR with whitepace indention
 [09:44:22] [main] ERROR [url/location] - A MULTI LINE ERROR with tab indention
 [09:44:22] [main] WARN [url/location] - ANOTHER ONE LINE WARN
    
por 14.07.2016 / 18:36
1

GNU grep é capaz de fazer isso de forma bastante simples. De man grep :

Two regular expressions may be joined by the infix operator |; the resulting regular expression matches any string matching either subexpression.

grep "ERROR\|FAIL\|WARN" /path/to/example.log

egrep elimina a necessidade de escapar dos símbolos | .

egrep "ERROR|FAIL|WARN" /path/to/example.log
    
por 14.07.2016 / 19:20
1

Agora que seu formato de dados foi estabelecido, a resposta se torna muito mais simples: grep foi criado para este .

Use como grep '<PATTERN>' <dataFile>

Em que <PATTERN> é SearchWORD1 ou SearchW1\|SearchW2

A resposta abaixo foi escrita, quando eu e @murphy ainda tínhamos suposições erradas sobre o formato de dados:

Aqui está um programa awk de uma linha que procura apenas por ERROR :

awk '/ERROR/{a=1;print} /^ / || /^\t/ {if (a) print;next} !/ERROR/ {a=0}'

Você poderia transformar isso em uma função de shell flexível com o parâmetro:

searchlog(){ awk -f <( echo "
/$1/{a=1;print}
/^ /||/^\t/{if (a) print;next}
! /$1/{a=0}
"); }

Execute como LogData_generated_by_program | searchlog <PATTERN> ou searchlog <PATTERN> < File_containing_Log_Data .

Para o formato de dados de exemplo, o outro respondente "adivinhou", isso resulta em:

$ searchlog ERROR < /tmp/exampleData
[09:44:22] [main] ERROR [url/location] - A ONE LINE ERROR
[09:44:22] [main] ERROR [url/location] - A MULTI LINE ERROR 
    with whitepace indention
[09:44:22] [main] ERROR [url/location] - A MULTI LINE ERROR 
       with tab indention
    
por 14.07.2016 / 18:49