[SP-pm] Capturar trechos de um arquivo de log

Gabriel Andrade de Santana gabiruh at gmail.com
Mon Mar 14 05:55:23 PDT 2011


2011/3/13 Tiago Peczenyj <tiago.peczenyj at gmail.com>:
> Flavio
>
> Imagine que vc quer imprimir todas as linhas entre uma string X e outra Y.
> Pode ser o começo e o fim de um StackTrace Java por exemplo. Vc pode ter uma
> "flag" $imprime quando encontra X e desliga quando encontra Y.
> É uma maquina de estados pois vc tem 2 estados definidos: "dentro" e "fora"
> do que vc quer imprimir.

Esse tipo de comportamento, onde uma flag determina se estamos dentro
ou fora de um intervalo, pode ser emulado utilizando o operador de
intervalo (..) quem em contexto escalar[1][2] age como um flip-flop[3]
armazenando o estado booleano resultante das próximas avaliações.

Em if($linha =~ /foo/ .. $linha =~ /bar/) {} o resultado da operação
será sempre verdadeiro a partir do momento em que $linha contiver
"foo" e assim permanecerá através das sucessivas chamadas até que
$linha contenha "bar" e então retornará falso NA PRÓXIMA execução do
teste no bloco if.

A solução do Nelson poderia ser (porcamente) reescrita assim:

====
use strict;
use warnings;

my @buffer;
my $has_error;

while (<>) {
  if ( /Starting/ .. /End/ ) { # ainda estamos entre "Starting" e "End"?
    $has_error = 1 if !$has_error && m/FAIL|WARNING|ERROR/;
    push @buffer, $_;
  }
  else {
    send_email( \@buffer ), $has_error = 0 if $has_error;
    @buffer = ();
  }
}

====
$ perl script.pl arquivo.log

Aviso: esse código tem o intuito de somente demonstrar de forma
simplista o uso do operador supracitado e não figura como um todo um
exemplo de boas práticas nem como solução definitiva para o problema.
Cabendo, portanto, ao bom entendedor transformar em algo útil as
minhas meias-palavras. :)


[1] http://perldoc.perl.org/perlop.html#Range-Operators
[2] http://tinyurl.com/ybfanvv
[3] http://pt.wikipedia.org/wiki/Flip-flop


More information about the SaoPaulo-pm mailing list