Ich habe eine Datei mit vielen Zeilen, und jede Zeile hat am Anfang einen Zeitstempel wie
[Thread-3] (21/09/12 06:17:38:672) logged message from code.....
Daher überprüfe ich häufig zwei Dinge aus dieser Protokolldatei.
- Die ersten paar Zeilen, die die globalen Bedingungen und die Startzeit haben, sind ebenfalls angegeben.
- Letzte paar Zeilen, die den Exit-Status mit einigen anderen Informationen haben.
Gibt es einen einfachen Befehl, mit dem ich nur die ersten und letzten Zeilen einer Datei anzeigen kann?
head and tail
funktioniert bei Ihnen nicht?N
sed(1)
Experte, aber es gibt Möglichkeiten, Dinge für die spätere Verwendung zu verstauen. Vielleicht zahlt es sich aus, dort nachzuschauen. OTOH, ich würde wahrscheinlich ein Perl-Skript (oder was auch immer) entwickeln, um dies zu tun, wenn es häufig verwendet wird, da ich damit besser vertraut bin.Antworten:
Sie können
sed
oder verwendenawk
, um es mit einem Befehl zu machen. Sie verlieren jedoch an Geschwindigkeit, Ursachesed
undawk
müssen trotzdem die gesamte Datei durchlaufen. Aus Sicht der Geschwindigkeit ist es viel besser, eine Funktion oder jedes Mal eine Kombination vontail
+ zu erstellenhead
. Dies hat den Nachteil, dass es nicht funktioniert, wenn die Eingabe eine Pipe ist. Sie können jedoch die Prozessersetzung verwenden, falls Ihre Shell dies unterstützt (siehe Beispiel unten).und starte es einfach als
Um mit der Prozessersetzung fortzufahren (nur bash, zsh, ksh wie Shells):
ps. Sie können sogar ein hinzufügen
grep
, um zu überprüfen, ob Ihre "globalen Bedingungen" vorliegen.quelle
-n 10
ist die Standardeinstellung, nein?-n 10
ist hier nicht notwendig.Bei @rush ist es richtig, dass head + tail für große Dateien effizienter ist. Bei kleinen Dateien (<20 Zeilen) werden einige Zeilen möglicherweise zweimal ausgegeben.
wäre genauso effizient, hätte aber das obige Problem nicht.
quelle
{head; tail;} < file
in zsh, scheitert aber in sh.{ head; tail;} < file
funktioniert immer. Entschuldigung für den Lärm.head
, nicht mit der Shell. Bei POSIX musshead
der Cursor in der Datei hinter diesen 10 Zeilen für reguläre Dateien bleiben. Ein Problem könnte bei Nicht-POSIX-head
Implementierungen auftreten (sehr alte Versionen von GNU head waren in diesem Fall nicht konform, aber wir sprechen von Jahrzehnten) oder wenn die Datei nicht suchbar ist (wie Named Pipe oder Socket, aber dann das andere Lösung hätte das gleiche Problem).sudo sh -c '{ head; tail;} < /path/to/file'
Die
{ head; tail; }
Lösung wäre nicht Arbeit an Rohren (oder Buchsen oder andere nicht-seekable Dateien) , weilhead
zu viele Daten verbrauchen könnte , wie es durch die Blöcke liest und kann nicht auf einem Rohr suchen zurück möglicherweise in der Datei den Cursor verlassen das hinaus , wastail
bedeutet , auswählen.Sie können also ein Tool verwenden, das wie die Shell jeweils ein Zeichen liest
read
(hier mit einer Funktion, die die Anzahl der Kopf- und Endzeilen als Argumente verwendet).oder implementieren Sie
tail
in awk zum Beispiel als:Mit
sed
:(Beachten Sie jedoch, dass bei einigen
sed
Implementierungen die Größe des Musterbereichs gering ist, sodass große Werte für die Anzahl der Endzeilen fehlschlagen würden.)quelle
Mit der
bash
Prozessersetzung können Sie Folgendes tun:Beachten Sie, dass die Zeilen nicht unbedingt in Ordnung sind, bei Dateien, die länger als ca. 8 KB sind, ist dies jedoch sehr wahrscheinlich. Diese 8-KB-Grenze entspricht der typischen Größe des Lesepuffers und hängt mit dem Grund zusammen, warum
| {head; tail;}
kleine Dateien nicht funktionieren.Das
cat >/dev/null
ist notwendig, um diehead
Pipeline am Leben zu erhalten. Andernfallstee
wird das Programm vorzeitig beendet, und während die Ausgabe von erfolgttail
, erfolgt die Ausgabe eher in der Mitte der Eingabe als am Ende.Zum Schluss, warum,
>/dev/null
anstatttail
zu einem anderen zu ziehen|
? Im folgenden Fall:head
s stdout wirdtail
eher in die Pipe als in die Konsole eingespeist , was wir überhaupt nicht wollen.quelle
tail
sie länger arbeiten muss, aber ich erwarte (und sehe), dass es bei kurzen Eingaben etwa die Hälfte der Zeit fehlschlägt.tee >(head) >(tail)
den gleichen Gründen (>(...)
die übrigens eine ksh-Funktion ist, die jetzt sowohl von zsh als auch von bash unterstützt wird), die auch Pipes verwenden. Sie könnten dies tun,... | (trap '' PIPE; tee >(head) >(tail) > /dev/null)
aber es werden immer noch Fehlermeldungen mit unterbrochenen Leitungen angezeigttee
.tail
wird der von SIGPIPE getötet, nichttee
undtail
schreibt nicht in eine Pipe. Also muss es von einem stammenkill()
, oder ?. Und das passiert nur, wenn ich die|
Syntax verwende.strace
sagt,tee
das ruft nicht ankill()
... also vielleichtbash
?seq 100000 | tee >(head -n1) >(tail -n1) > /dev/null
Verwenden von
ed
(wobei die gesamte Datei jedoch in den RAM gelesen wird):quelle
ed -s file <<< $'11,$-10d\n,p\nq\n'
Stephanes erste Lösung in einer Funktion, mit der Sie Argumente verwenden können (funktioniert in jeder Bourne-ähnlichen oder POSIX-Shell):
Jetzt können Sie dies tun:
Dies setzt natürlich voraus, dass Sie nur eine Datei betrachten und Stephanes Lösung (zuverlässig) nur für reguläre (durchsuchbare) Dateien funktioniert.
quelle
Mit der
-u
(--unbuffered
) Option von GNUsed
können Siesed -u 2q
als ungepufferte Alternative verwendenhead -n2
:(head -n2;tail -n2)
schlägt fehl, wenn die letzten Zeilen Teil des Blocks der Eingabe sind, die verwendet wird vonhead
:quelle
Ich bin heute auf so etwas gestoßen, wo ich nur die letzte Zeile und ein paar Zeilen von der Vorderseite eines Baches brauchte und mir die folgenden einfallen ließ.
Ich las dies wie folgt: Initialisiere den Haltebereich mit dem Inhalt der ersten Zeile, hänge die Zeilen 2-3 an den Haltebereich an, füge bei EOF die letzte Zeile an den Haltebereich an, tausche den Halte- und Musterbereich aus und drucke das Muster Platz.
Vielleicht kann jemand mit mehr
sed
-fu als ich herausfinden, wie man dies verallgemeinert, um die letzten paar Zeilen des in dieser Frage angegebenen Streams zu drucken , aber ich brauchte es nicht und konnte keinen einfachen Weg finden, basierend auf der$
Adresse zu rechnen insed
oder vielleicht durch Verwalten des Laderaums, so dass nur die letzten Zeilen darin sind, wennEOF
erreicht wird.quelle
Sie können Perl ausprobieren, wenn Sie es installiert haben:
Dies funktioniert für die meisten Dateien, liest jedoch die gesamte Datei in den Speicher, bevor sie verarbeitet wird. Wenn Sie mit Perl-Slices nicht vertraut sind, bedeutet "0" in eckigen Klammern "Erste Zeile" und "-3 ...- 1" "Letzte drei Zeilen". Sie können beide auf Ihre Bedürfnisse zuschneiden. Wenn Sie sehr große Dateien verarbeiten müssen (was "groß" ist, hängt möglicherweise von Ihrem Arbeitsspeicher ab und möglicherweise von der Größe der Auslagerungsdateien), können Sie Folgendes auswählen:
Es kann etwas langsamer sein, da bei jeder Iteration ein Slice erstellt wird, dies ist jedoch unabhängig von der Dateigröße.
Beide Befehle sollten sowohl in Pipes als auch mit regulären Dateien funktionieren.
quelle