Was ist das Gegenteil von Kopf? Ich möchte alle bis auf die ersten N Zeilen einer Datei

142

Wie kann ich bei einer Textdatei unbekannter Länge beispielsweise alle bis auf die ersten beiden Zeilen der Datei lesen ? Ich weiß tail, dass ich die letzten N Zeilen bekomme, aber ich weiß nicht, was N vor der Zeit ist.

Also für eine Datei

AAAA
BBBB
CCCC
DDDD
EEEE

Ich will

CCCC
DDDD
EEEE

Und für eine Datei

AAAA
BBBB
CCCC

Ich würde nur bekommen

CCCC
Nicholas MT Elliott
quelle

Antworten:

210

tail --help gibt folgendes an:

  -n, --lines=K            output the last K lines, instead of the last 10;
                           or use -n +K to output lines starting with the Kth

Um die ersten 2Zeilen herauszufiltern , -n +3sollten Sie die gewünschte Ausgabe erhalten (ab dem 3.).

Joe Enos
quelle
2
Seltsamerweise listet meine Manpage die Option nicht auf, aber sie funktioniert einwandfrei - danke!
Nicholas MT Elliott
@Nicholas: Seltsam, ich dachte, es wäre Standarddokumentation, unabhängig vom Betriebssystem. Ich habe das aus Cygwin in Windows gezogen, daher weiß ich nicht, wie es in verschiedenen Linux-Distributionen aussieht. Ich bin froh, dass es funktioniert hat.
Joe Enos
@NicholasMTElliott man7 listet es wie die Manpage von Joe Enos auf, daher ist es wahrscheinlich ein Problem mit der Manpage-Version
Uli Köhler,
@SteveJorgensen: Ich verstehe nicht, worauf sich Ihr Kommentar bezieht. scheint niemand vorzuschlagen, dafür zu verwenden head?
Ruakh
21

Angenommen, Ihre Version von tail unterstützt dies, können Sie angeben, dass der Schwanz nach X-Linien gestartet werden soll. In Ihrem Fall würden Sie 2 + 1 tun.

tail -n +3

[mdemaria@oblivion ~]$ tail -n +3 stack_overflow.txt
CCCC
DDDD
EEEE
Mike DeMaria
quelle
12

Eine einfache Lösung mit awk:

awk 'NR > 2 { print }' file.name
janm
quelle
Einer von uns ist verwirrt. Die Frage lautet: "Alle bis auf die ersten beiden Zeilen der Datei". Wie erfüllt dieser Befehl die Anforderung nicht?
Janm
6
{ print }ist die Standardaktion und kann weggelassen werden.
Tripleee
8

Versuchen Sie es sed 1,2d. Ersetzen Sie 2 nach Bedarf.

lhf
quelle
funktionierte wie erwartet .. da die Anzahl der Zeilen nach den ersten 2 Zeilen unbekannt ist.
Kumarprd
6

tail -n +linecount filenamestartet die Ausgabe in Zeile linecountvon filename, tail -n +3 filename sollte also tun, was Sie wollen.

Jim Lewis
quelle
Das würde in meiner Shell nicht funktionieren, würde aber funktionieren tail -n +17 filename. Ich benutze Bash / Ubuntu LTS
Isomorphismen
2
@iso: Danke für das Heads-up - ältere Versionen von haben taildie Syntax akzeptiert, die ich in meiner ursprünglichen Antwort verwendet habe, aber jetzt muss man die explizite -nOption verwenden. Ich habe meine Antwort entsprechend aktualisiert.
Jim Lewis
0

Verwenden Sie diese Option, wenn das erste Sample dann sample1.dat heißt tail --lines=3 sample1.datund alle Zeilen von der 3. bis zur letzten Zeile gedruckt werden.

Nehmen wir für das zweite Beispiel erneut an, es heißt sample2.dat und tail --lines=-1 sample2.datdruckt die letzte Zeile ...

t0mm13b
quelle
@ Jim: Was ist der Unterschied zwischen dir und mir? .... dasselbe ....: o Ich bezog mich auf die beiden Eingaben der Beispieldatendatei gemäß seiner Frage und zeigte, wie man das erreicht, wonach er suchte ... .
t0mm13b
Ok ... warum hat er dann nach dem zweiten Beispiel gefragt und das gewünschte Ergebnis gezeigt? Ich habe 'tail --lines = -1' verwendet. Natürlich können Sie den Dateinamen komplett weglassen und es ist immer noch kann als Rohr wirken ... hmm
t0mm13b
@tommie: Ups, vergiss was ich über Rohre gesagt habe ... Ich muss an ein anderes Dienstprogramm gedacht haben. Mein Punkt war jedoch, dass ein einzelner Befehl tail +3 anyfiledie gewünschten Ergebnisse für den allgemeinen Fall liefert, während tail --lines=NN im Voraus bekannt sein muss, um das gewünschte Ergebnis zu erzielen.
Jim Lewis
@tommie: Aber das ist tail... sollte das nicht "Bottoms Up" sein? (Ba-dum TISH! Danke, ich werde die ganze Woche hier sein ...)
Jim Lewis
0

Ich weiß wirklich nicht, wie ich es nur mit dem Schwanz oder dem Kopf machen soll, aber mit Hilfe von wc -l(Zeilenanzahl) und Bash-Ausdruck können Sie das erreichen.

tail -$(( $( wc -l $FILE | grep -Eo '[0-9]+' ) - 2 )) $FILE

Hoffe das hilft.

NawaMan
quelle
1
Dies erfordert einen vollständigen Durchlauf der Datei, bevor tail ausgeführt wird. Wenn die Datei größer als der Speicher ist, ist dies sehr ineffizient. Dateien mit weniger als zwei Zeilen werden nicht verarbeitet. Es behandelt nicht die Größe der Datei, die die Größe zwischen dem WC und dem Tail ändert.
Januar
2
@janm: Dir geht es gut. Andere Antworten sind einfach besser. Es ist mir peinlich. :-p
NawaMan
-1

Verwenden Sie awk, um alle bis auf die letzten 2 Zeilen zu erhalten

awk 'FNR==NR{n=FNR}FNR<=n-3{print}' file file

awk, um alle bis auf die ersten 2 Zeilen zu bekommen

awk 'NR>2' file

ODER Sie können mehr verwenden

more +2 file

oder einfach nur schlagen

#!/bin/bash

i=0
while read -r line
do
  [[ $i > 1 ]] && echo "$line"
  ((i++))
done <"file"
Ghostdog74
quelle
Dies entspricht nicht den Anforderungen. Die Frage lautet "alle bis auf die ersten beiden Zeilen der Datei" und enthält zwei Beispiele mit jeweils einer einzelnen Datei, bei denen die ersten beiden Zeilen übersprungen und der Rest der Datei an stdout gesendet wird. Das macht dieser Befehl nicht.
Januar
Ja, ich habe die Frage falsch verstanden. dachte, er wird nach allen bis auf die letzten 2 Zeilen gefragt.
Ghostdog74