Como executar um multiline grep em vários arquivos?

5

Estou tentando pegar esse padrão onde quer que ele ocorra em vários arquivos de log (Nota: esses padrões podem variar muito em tamanho, ou seja, a quantidade de Blahs):

   Found an txt File
    Blah
    Blah
    10019874
    Blah
    Blah
    Processed File   

Usando esta linha de comando:

 pcregrep -M 'Found an.*(\n|.)*10019874.*(\n|.)*Processed' log_*.txt

Meu regex verifica REGEX AQUI

Estou usando pcregrep com o sinalizador -M multiline. Ele irá em qualquer arquivo de log que comece com 'log_' e termine com '.txt'. Quando executo este comando, ele retorna "Falha de segmentação"

Existe uma maneira mais simples / melhor de fazer isso?

    
por blarg 19.06.2014 / 15:08

1 resposta

4

Como eu disse no meu comentário, o comando que você postou funciona bem no meu LMDE (pcregrep versão 8.31 2012-07-06). No entanto, como o seu regex especifica apenas parte da string que você está procurando, você também pode fazer isso com o% normalgrep:

grep -A 6 'Found an' log_*.txt | grep -C 3 10019874

O -A 6 imprimirá a linha correspondente à string passada e as 6 linhas seguintes e o -C 3 imprimirá as 3 linhas circundantes . O resultado final é exatamente o mesmo que a abordagem pcregrep que você estava usando.

Se o seu padrão pode ter diferentes números de linhas, isso pode explicar o segfault. Presumivelmente, em alguns dos seus arquivos, a seção correspondente é muito longa e causa um erro de falta de memória. Uma maneira de contornar isso seria um pequeno script:

perl -ne '$c=1 if /Found an/; ## set $c to 1 if this line matches 'Found on'
          if($c){               ## If $c is defined and non-0
            push @F,$_;         ## Add the current line to the @F array
            $c++ if /10019874/; ## Increment $c if this line matches '10019874'
            if(/Processed/){    ## If this line matches 'Processed'
                print "@F" if $c>1; ## Print the contents of @F if $c is >1
                @F=""; $c=0;         ## Empty @F, set $c to 0.
            }
           }' log_*.txt 

A mesma coisa que um revestimento:

perl -ne '$c=1 if /Found an/; if($c){push @F,$_; $c++ if /10019874/; if(/Processed/){print "@F" if $c>1; @F=""; $c=0;}}' log_*txt 
    
por 19.06.2014 / 15:22