Como executar um grep multilinha em vários arquivos?

Como executar um grep multilinha em vários arquivos?

Estou tentando capturar esse padrão onde quer que ele ocorra em vários arquivos de log (Observação: esses padrões podem variar muito em tamanho, ou seja, na 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 verificaREGEX AQUI

Estou usando pcregrep com o sinalizador multilinha -M. Ele estará 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?

Responder1

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

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

Ele -A 6imprimirá a linha correspondente à string passada e as 6 linhas seguintes e -C 3imprimirá as 3em torno dalinhas. O resultado final é exatamente igual à pcregrepabordagem que você estava usando.


Se o seu padrão puder ter números diferentes de linhas, isso pode explicar a falha de segmento. 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 pouco de 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 forro:

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 

informação relacionada