Wie erhält man ein inverses Verhalten für "Schwanz" und "Kopf"?


55

Gibt es eine Möglichkeit zu head/ tailein Dokument und erhält den umgekehrten Ausgang; weil Sie nicht wissen, wie viele Zeilen ein Dokument enthält?

Das heißt, ich möchte nur alles außer den ersten zwei Zeilen foo.txtzum Anhängen an ein anderes Dokument erhalten.

Antworten:


57

Hiermit können Sie die ersten beiden Zeilen entfernen:

tail -n +3 foo.txt

und dies, um die letzten beiden Zeilen zu entfernen:

head -n -2 foo.txt

(vorausgesetzt die Datei endet mit \nfür letztere)


Genau wie bei der Standardnutzung von tailund sind headdiese Vorgänge nicht destruktiv. Verwenden >out.txtSie diese Option, wenn Sie die Ausgabe in eine neue Datei umleiten möchten:

tail -n +3 foo.txt >out.txt

Falls out.txtbereits vorhanden, wird diese Datei überschrieben. Verwenden Sie >>out.txtanstelle von, >out.txtwenn die Ausgabe lieber angehängt werden soll out.txt.


3
re „Kopf, wenn die Datei mit der Endung \n“ .. Es funktioniert für alle negativen ganzen Zahlen außer -n -0denen gibt gar nichts , so wie -n 0würde (mit: Kopf (GNU coreutils) 7.4) ... Wenn jedoch ein nachlauf \nvorhanden ist, -n -0macht Druck wie von der zu erwarten ist -, dh. er druckt die gesamte Datei ... So ist es für alle Nicht-Null negative Werte funktioniert .. aber -0schlägt fehl , wenn es keine Hinter ist\n
— Peter.O

@fred: In der Tat seltsam ... (dasselbe gilt für 8.12 hier).
— Stéphane Gimenez

Ist diese Operation destruktiv? Wie möchte ich, dass es die Umkehrung der ersten beiden Zeilen des Dokuments in eine andere kopiert?
— Chrisjlee

@Chris: Nein, sie drucken das Ergebnis einfach auf ihre "Standardausgabe", die normalerweise mit dem Terminal verbunden ist. Ich habe einige Details hinzugefügt, wie man die Ausgabe zu einigen Dateien umleitet.
— Stéphane Gimenez

7
head -n -2ist nicht POSIX-kompatibel .
— 10.

9

Wenn Sie alle außer den ersten N-1-Leitungen möchten, rufen Sie tailmit der Anzahl der Leitungen an +N. (Die Nummer ist die Nummer der ersten Zeile, die Sie beibehalten möchten, beginnend mit 1, dh +1 bedeutet, dass oben begonnen wird, +2 bedeutet, dass eine Zeile übersprungen wird usw.).

tail -n +3 foo.txt >>other-document

Es gibt keine einfache, tragbare Möglichkeit, die letzten N Zeilen zu überspringen. GNU headerlaubt head -n +Nals Gegenstück von tail -n +N. Andernfalls, wenn Sie tac(zB GNU oder Busybox) haben, können Sie es mit Tail kombinieren:

tac | tail -n +3 | tac

Portabel können Sie einen awk-Filter verwenden (ungetestet):

awk -vskip=2 '{
    lines[NR] = $0;
    if (NR > skip) print lines[NR-skip];
    delete lines[NR-skip];
}'

Wenn Sie die letzten Zeilen aus einer großen Datei entfernen möchten, können Sie den Byte-Versatz des zu schneidenden Teils bestimmen und anschließend die Kürzung mit ausführen dd.

total=$(wc -c < /file/to/truncate)
chop=$(tail -n 42 /file/to/truncate | wc -c)
dd if=/dev/null of=/file/to/truncate seek=1 bs="$((total-chop))"

Sie können eine Datei am Anfang nicht abschneiden. Wenn Sie jedoch die ersten Zeilen einer großen Datei entfernen müssen, können Sie den Inhalt verschieben .


Auf einigen Systemen (wie modernen Linux) können Sie eine Datei am Anfang abschneiden (komprimieren), in der Regel jedoch nur um ein Vielfaches der FS-Blockgröße (in diesem Fall also nicht wirklich nützlich).
— Stéphane Chazelas

3

Aus der tailManpage (also GNU tail):

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

Daher sollten im Folgenden alle bis auf die ersten zwei Zeilen von somefile.txtan angehängt werden anotherfile.txt:

tail --lines=+3 somefile.txt >> anotherfile.txt

3

Zum Entfernen der ersten n Zeilen kann GNU sed verwendet werden. Zum Beispiel, wenn n = 2 ist

sed -n '1,2!p' input-file

Der !Mittelwert "dieses Intervall ausschließen". Wie Sie sich vorstellen können, kann zum Beispiel ein komplizierteres Ergebnis erzielt werden

sed -n '3,5p;7p'

das wird Linie 3,4,5,7 zeigen. Die Verwendung regulärer Ausdrücke anstelle von Adressen erhöht die Leistung.

Die Einschränkung besteht darin, dass die Zeilennummern im Voraus bekannt sein müssen.


1
Warum nicht einfach sed 1,2d? Einfacher ist normalerweise besser. Auch ist nichts in Ihren Beispielen spezifisch für GNU Sed; Ihre Befehle verwenden alle die POSIX- Standardfunktionen von Sed .
— Wildcard

1

Sie können diffdie Ausgabe von head/ tailmit der Originaldatei vergleichen und dann das Gleiche entfernen, um die Umkehrung zu erhalten.

diff --unchanged-group-format='' foo.txt <(head -2 foo.txt)

1

Während tail -n +4die Ausgabe der Datei ab der 4. Zeile (alle bis auf die ersten 3 Zeilen) Standard und portabel ist, ist dies nicht das headGegenstück ( head -n -3alle bis auf die letzten 3 Zeilen).

Portabel, würden Sie tun:

sed '$d' | sed '$d' | sed '$d'

Oder:

sed -ne :1 -e '1,3{N;b1' -e '}' -e 'P;N;D'

(Beachten Sie, dass auf einigen Systemen, auf denen sedein Musterbereich von begrenzter Größe vorhanden ist, dieser nicht auf große Werte von skaliert n).

Oder:

awk 'NR>3 {print l[NR%3]}; {l[NR%3]=$0}'

1
{   head -n2 >/dev/null
    cat  >> other_document
}   <infile

Wenn <infilees sich um eine reguläre, lseek()-fähige Datei handelt, fühlen Sie sich auf jeden Fall frei. Das obige ist ein vollständig POSIX-unterstütztes Konstrukt.


0

Mein Ansatz ist ähnlich wie bei Gilles, aber ich kehre die Datei mit cat und pipe einfach mit dem Befehl head um.

tac -r thefile.txt | head thisfile.txt (ersetzt Dateien)


0

Hoffe, ich habe Ihr Bedürfnis klar verstanden.

Sie haben verschiedene Möglichkeiten, Ihre Anfrage zu bearbeiten:

tail -n$(expr $(cat /etc/passwd|wc -l) - 2) /etc/passwd

Wo / etc / passwd ist Ihre Datei

Die 2. Lösung kann nützlich sein, wenn Sie eine große Datei haben:

my1stline=$(head -n1 /etc/passwd)
my2ndline=$(head -n2 /etc/passwd|grep -v "$my1stline")
cat /etc/passwd |grep -Ev "$my1stline|$my2ndline"

0

Lösung für BSD (macOS):

Entfernen Sie die ersten 2 Zeilen:

tail -n $( echo "$(cat foo.txt | wc -l)-2" | bc )

Letzte 2 Zeilen entfernen:

head -n $( echo "$(cat foo.txt | wc -l)-2" | bc )

... nicht sehr elegant, aber erledigt den Job!

Durch die Nutzung unserer Website bestätigen Sie, dass Sie unsere Cookie-Richtlinie und Datenschutzrichtlinie gelesen und verstanden haben.
Licensed under cc by-sa 3.0 with attribution required.