Prägnante Möglichkeit, alle Zeilen bis zur letzten Zeile zu drucken, die mit einem bestimmten Muster übereinstimmt

7

Ich versuche einen prägnanten Shell-One-Liner zu finden, der mir alles geben wird Zeilen in einer Datei bis zu ein Muster.

Der Anwendungsfall besteht darin, alle Zeilen in einer Protokolldatei auszugeben, bis ich einige finde Markierung, die anzeigt, dass der Server neu gestartet wurde.

Hier ist eine dumme Shell-only-Methode:

%Vor%

Ein etwas zuverlässigerer Perl-Weg, der die Datei auf stdin nimmt:

%Vor%

Und natürlich könnten Sie das effizienter tun, wenn Sie die Datei öffnen, suche bis zum Ende und suche zurück, bis du eine passende Zeile gefunden hast.

Es ist einfach, alles ab dem ersten Vorkommen zu drucken, z. B .:

%Vor%

Aber ich habe mir keine Möglichkeit ausgedacht, um alles ab dem letzten zu drucken Vorkommen.

    
Ævar Arnfjörð Bjarmason 22.01.2012, 16:33
quelle

7 Antworten

6

Hier ist eine sed-only-Lösung. So drucken Sie jede Zeile in $file beginnend mit die letzte Zeile, die mit $pattern übereinstimmt:

%Vor%

Beachten Sie, dass dies wie Ihre Beispiele nur dann funktioniert, wenn die Datei das Muster enthält. Andernfalls wird die gesamte Datei ausgegeben.

Hier ist eine Zusammenfassung dessen, was es macht, mit sed-Befehlen in Klammern:

  • [H] Hängen Sie jede Zeile an seds "hold space" an, aber nicht an stdout [d].
  • Wenn wir auf das Muster treffen, [h] wirf den Hold-Raum weg und beginne mit der passenden Zeile neu.
  • Wenn wir das Ende der Datei erreicht haben, kopieren Sie den Haltebereich in den Musterbereich [g], so dass er auf stdout zurückkommt.

Beachten Sie auch, dass es bei sehr großen Dateien wahrscheinlich langsam wird, da jede Single-Pass-Lösung eine Reihe von Zeilen im Speicher behalten muss.

    
Rob Davis 23.01.2012 05:54
quelle
4

Laden Sie die Daten zeilenweise in ein Array und werfen Sie das Array weg, wenn Sie ein Muster gefunden haben. Drucken Sie aus, was am Ende noch übrig ist.

%Vor%

Als One-Liner:

%Vor%     
mob 22.01.2012 20:06
quelle
4

Alternativ: tac "$file" | sed -n '/PATTERN/,$p' | tac

EDIT: Wenn Sie tac nicht haben, emulieren Sie es, indem Sie

definieren %Vor%

Hässlich, aber POSIX.

    
Jo So 22.01.2012 17:00
quelle
3

Ich schlage eine Vereinfachung Ihres Shell-Skripts vor:

%Vor%

Es ist wesentlich prägnanter, weil es:

  • Verwendet die Option + des Tails, um von der gegebenen Zeile bis zum Ende zu drucken, anstatt die Entfernung von dort bis zum Ende zu berechnen.
  • Verwendet präzisere Möglichkeiten, Befehlszeilenoptionen auszudrücken.

Und es behebt einen Fehler, indem er $ file zitiert (so wird es bei Dateien funktionieren, deren Namen Leerzeichen enthalten).

    
John Zwinck 22.01.2012 16:47
quelle
3

Seds q Befehl wird den Trick machen:

%Vor%

Dadurch werden alle Zeilen gedruckt, bis sie die Zeile mit dem Muster erreichen. Danach wird sed die letzte Zeile drucken und beenden.

    
David W. 23.01.2012 00:26
quelle
1

Der Titel und die Beschreibung dieser Fragen stimmen nicht überein.

Für den Titel der Frage +1 für die Antwort von @David W. Auch:

%Vor%

Für die Frage im Körper haben Sie bereits einige Lösungen.

Beachten Sie, dass tac wahrscheinlich spezifisch für Linux ist. Es scheint nicht in BSD oder OSX zu existieren. Wenn Sie eine Lösung mit mehreren Plattformen möchten, verlassen Sie sich nicht auf tac.

Natürlich erfordert jede Lösung, dass Ihre Daten entweder im Speicher gespoolt oder einmal zur Analyse und ein zweites Mal zur Verarbeitung gesendet werden. Zum Beispiel:

%Vor%

Beachten Sie, dass meine Verwendung von tail für FreeBSD ist. Wenn Sie Linux verwenden, benötigen Sie wahrscheinlich tail -n $n $tmpfile .

    
ghoti 23.01.2012 06:23
quelle
1

Rob Davis hat mir gezeigt, was Sie gesagt wollten, was Sie wirklich wollten:

Du hast gesagt:

  

Ich versuche einen prägnanten Shell-One-Liner zu finden, der mir alle Zeilen in einer Datei bis ein Muster geben wird.

Aber dann, am Ende deines Beitrags, hast du gesagt:

  

Aber ich habe keine Möglichkeit gefunden, alles ab zu drucken.

Ich habe Ihnen bereits die Antwort auf Ihre erste Frage gegeben. Hier ist eine einzeilige Antwort für Ihre zweite Frage: Drucken von einem regulären Ausdruck bis zum Ende der Datei:

%Vor%

Ein ähnlicher Perl-One-Liner:

%Vor%     
David W. 23.01.2012 16:28
quelle

Tags und Links