Der Grund warum
tac file | grep foo | head -n 1
hört nicht beim ersten Treffer auf, liegt an der Zwischenspeicherung.
Wird normalerweise head -n 1nach dem Lesen einer Zeile beendet. Also grepsollte 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 greppuffert. Das heißt, es wird nicht geschrieben, bis es genug akkumuliert hat (4096 Bytes in meinem Test mit GNU grep).
Das heißt, es grepwird nicht beendet, bevor 8192 Datenbytes geschrieben wurden, also wahrscheinlich ziemlich viele Zeilen.
Mit GNU grepkönnen Sie das Programm schneller beenden, indem --line-bufferedSie festlegen, dass Zeilen geschrieben werden sollen, sobald sie gefunden werden, unabhängig davon, ob sie zu einem Terminal geleitet werden oder nicht. So grepwürde dann die zweite Zeile verlassen, die es findet.
Aber mit GNU grepkannst du es trotzdem verwenden, -m 1wie @terdon gezeigt hat, was besser ist, wenn es beim ersten Match beendet wird.
Wenn Sie grepnicht GNU sind grep, können Sie stattdessen sedoder awkverwenden. Da tac es sich jedoch um einen GNU-Befehl handelt, bezweifle ich, dass Sie ein System finden, bei tacdem grepGNU nicht verwendet wird grep.
tac file | sed "/$pattern/!d;q" # BRE
tac file | P=$pattern awk '$0 ~ ENVIRON["P"] {print; exit}' # ERE
Einige Systeme müssen tail -rdasselbe tun wie GNU tac.
Beachten Sie, dass für eine regelmäßige (durchsuchbar) Dateien, tacund tail -rsind 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 oder tacauf nicht-regulären Dateien würde) .
Auf Systemen, auf denen weder verfügbar tacnoch tail -rverfügbar sind, besteht die einzige Möglichkeit darin, das Rückwärtslesen von Hand mit folgenden Programmiersprachen zu implementieren perl:
grep -e "$pattern" file | tail -n1
Oder:
sed "/$pattern/h;$!d;g" file
Aber das bedeutet, alle Übereinstimmungen zu finden und nur die letzte zu drucken.