Wie führe ich ein mehrzeiliges Grep über mehrere Dateien aus?

Wie führe ich ein mehrzeiliges Grep über mehrere Dateien aus?

Ich versuche, dieses Muster überall dort zu erfassen, wo es in mehreren Protokolldateien auftritt (Hinweis: Die Größe dieser Muster, d. h. die Anzahl der Blahs, kann stark variieren):

   Found an txt File
    Blah
    Blah
    10019874
    Blah
    Blah
    Processed File   

Verwenden Sie diese Befehlszeile:

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

Mein regulärer Ausdruck ist in OrdnungREGEX HIER

Ich verwende pcregrep mit dem mehrzeiligen Flag -M. Es wird in allen Protokolldateien verwendet, die mit „log_“ beginnen und mit „.txt“ enden. Wenn ich diesen Befehl ausführe, wird „Segmentation Fault“ zurückgegeben.

Gibt es eine einfachere/bessere Möglichkeit, dies zu tun?

Antwort1

Wie ich in meinem Kommentar sagte, funktioniert der von Ihnen gepostete Befehl auf meinem LMDE (pcregrep Version 8.31 2012-07-06) einwandfrei. Da Ihr regulärer Ausdruck jedoch nur einen Teil der gesuchten Zeichenfolge angibt, können Sie dies auch mit normal tun grep:

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

Das -A 6druckt die Zeile, die der übergebenen Zeichenfolge entspricht, und die 6 folgenden Zeilen und das -C 3druckt die 3UmgebungZeilen. Das Endergebnis ist genau dasselbe wie bei dem pcregrepAnsatz, den Sie verwendet haben.


Wenn Ihr Muster unterschiedliche Zeilenzahlen haben kann, kann das den Segmentierungsfehler erklären. Vermutlich ist der übereinstimmende Abschnitt in einigen Ihrer Dateien zu lang und verursacht einen Speicherfehler. Eine Möglichkeit, dies zu umgehen, wäre ein wenig Skripting:

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 

Das Gleiche wie ein Einzeiler:

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 

verwandte Informationen