Ich habe eine Datei mit ca. 30.000.000 Zeilen (Radius Accounting) und muss die letzte Übereinstimmung eines bestimmten Musters finden.
Der Befehl:
tac accounting.log | grep $pattern
gibt was ich brauche, ist aber zu langsam, da das OS erst die ganze Datei lesen und dann an die Pipe senden muss.
Ich brauche also etwas Schnelles, das die Datei von der letzten bis zur ersten Zeile lesen kann.
quelle
tac
. Mein Punkt war, dass es nur hilft, wenn Sie es auch verwenden,-m
da die Datei von zwei Programmen noch vollständig gelesen werden muss. Ansonsten könnten Sie einfach nach allen Vorkommen suchen und nur das letzte behalten, wie ich es tuetail -n 1
.grep -m
sollte es sehr effizient sein.grep -m
damit ist. Das OP verwendete nicht,-m
so dass sowohl grep als auch tac das Ganze verarbeiteten.awk
Zeile erläutern?Der Grund warum
hört nicht beim ersten Treffer auf, liegt an der Zwischenspeicherung.
Wird normalerweise
head -n 1
nach dem Lesen einer Zeile beendet. Alsogrep
sollte man sich ein SIGPIPE zulegen und gleich beenden, sobald es seine zweite Zeile schreibt.Aber was passiert ist, dass, weil seine Ausgabe nicht an ein Terminal geht, es
grep
puffert. Das heißt, es wird nicht geschrieben, bis es genug akkumuliert hat (4096 Bytes in meinem Test mit GNU grep).Das heißt, es
grep
wird nicht beendet, bevor 8192 Datenbytes geschrieben wurden, also wahrscheinlich ziemlich viele Zeilen.Mit GNU
grep
können Sie das Programm schneller beenden, indem--line-buffered
Sie festlegen, dass Zeilen geschrieben werden sollen, sobald sie gefunden werden, unabhängig davon, ob sie zu einem Terminal geleitet werden oder nicht. Sogrep
würde dann die zweite Zeile verlassen, die es findet.Aber mit GNU
grep
kannst du es trotzdem verwenden,-m 1
wie @terdon gezeigt hat, was besser ist, wenn es beim ersten Match beendet wird.Wenn Sie
grep
nicht GNU sindgrep
, können Sie stattdessensed
oderawk
verwenden. Datac
es sich jedoch um einen GNU-Befehl handelt, bezweifle ich, dass Sie ein System finden, beitac
demgrep
GNU nicht verwendet wirdgrep
.Einige Systeme müssen
tail -r
dasselbe tun wie GNUtac
.Beachten Sie, dass für eine regelmäßige (durchsuchbar) Dateien,
tac
undtail -r
sind effizient , weil sie die Dateien rückwärts lesen tun, sind sie nicht nur die Datei vollständig im Speicher zu lesen , bevor sie rückwärts Druck (wie @ SLMs sed Ansatz odertac
auf nicht-regulären Dateien würde) .Auf Systemen, auf denen weder verfügbar
tac
nochtail -r
verfügbar sind, besteht die einzige Möglichkeit darin, das Rückwärtslesen von Hand mit folgenden Programmiersprachen zu implementierenperl
:Oder:
Aber das bedeutet, alle Übereinstimmungen zu finden und nur die letzte zu drucken.
quelle
Hier ist eine mögliche Lösung, die den Ort des ersten Auftretens des Musters vom letzten findet:
Hierfür werden die folgenden Schalter
-s
und verwendet :-r
tac
quelle
Mit sed
Es werden einige alternative Methoden @ Terdon der feinen Antwort mit
sed
:Beispiele
Perl verwenden
Als Bonus ist hier eine etwas einfachere Notation in Perl zu merken:
Beispiel
quelle
sed
eine) wahrscheinlich mehrere Größenordnungen langsamer alsgrep 5 | tail -n1
odersed '/5/h;$!d;g'
. Es wird möglicherweise auch viel Speicher verbrauchen. Es ist nicht viel portabler, da Sie immer noch GNUs verwendengrep -m
.