it-swarm.com.de

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

Gibt es eine Möglichkeit, ein Dokument zu head/tail und die umgekehrte Ausgabe zu erhalten? weil Sie nicht wissen, wie viele Zeilen ein Dokument enthält?

Das heißt, Ich möchte nur alles außer den ersten beiden Zeilen von foo.txt an ein anderes Dokument anhängen.

57
chrisjlee

Sie können dies verwenden, um die erste zwei Zeilen zu entfernen:

tail -n +3 foo.txt

und dies, um die letzten zwei Zeilen zu entfernen:

head -n -2 foo.txt

(vorausgesetzt, die Datei endet mit \n für letztere)


Genau wie bei der Standardverwendung von tail und head sind diese Operationen nicht destruktiv. Verwenden Sie >out.txt, Wenn Sie die Ausgabe in eine neue Datei umleiten möchten:

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

Falls out.txt Bereits vorhanden ist, wird diese Datei überschrieben. Verwenden Sie >>out.txt Anstelle von >out.txt, Wenn Sie die Ausgabe lieber an out.txt Anhängen möchten.

59

Wenn Sie alle bis auf die ersten N-1 Zeilen möchten, rufen Sie tail mit der Anzahl der Zeilen +N. (Die Zahl ist die Nummer der ersten Zeile, die Sie beibehalten möchten, beginnend bei 1, d. H. +1 bedeutet, dass Sie oben beginnen, +2 bedeutet, dass Sie eine Zeile überspringen usw.).

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

Es gibt keine einfache, tragbare Möglichkeit, die letzten N Zeilen zu überspringen. GNU head erlaubt head -n +N als Gegenstück zu tail -n +N. Wenn Sie andernfalls tac haben (z. B. GNU oder Busybox), können Sie es mit tail kombinieren:

tac | tail -n +3 | tac

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

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-Offset des abzuschneidenden Teils bestimmen und dann das Abschneiden mit dd durchführen.

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 der Manpage tail (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 beiden Zeilen von somefile.txt bis anotherfile.txt:

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

So entfernen Sie die ersten n Zeilen GNU sed kann verwendet werden. Zum Beispiel, wenn n = 2 ist

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

Das ! bedeutet "dieses Intervall ausschließen". Wie Sie sich vorstellen können, kann beispielsweise ein komplizierteres Ergebnis erzielt werden

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

das wird Zeile 3,4,5,7 zeigen. Die Verwendung regulärer Ausdrücke anstelle von Adressen bietet mehr Leistung.

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

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

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

2
mikeserv

Während tail -n +4 Die Ausgabe der Datei ab der 4. Zeile (alle bis auf die ersten 3 Zeilen) ist Standard und portabel. Ihr Gegenstück head (head -n -3, alle außer den letzten 3 Zeilen) ist nicht.

Tragbar 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 sed einen begrenzten Musterbereich hat, der nicht auf große Werte von n skaliert werden kann).

Oder:

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

Sie können diff verwenden, um die Ausgabe von head/tail mit der Originaldatei zu vergleichen und dann das Gleiche zu entfernen, um die Umkehrung zu erhalten.

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

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

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

0
Abe

Lösung für BSD (macOS):

Entfernen Sie die ersten 2 Zeilen:

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

Entfernen Sie die letzten 2 Zeilen:

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

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

0
spectrum

Ich hoffe, ich habe Ihr Bedürfnis klar verstanden.

Sie haben mehrere Möglichkeiten, um Ihre Anfrage abzuschließen:

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

Wobei / etc/passwd Ihre Datei ist

Die zweite 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
Mathieu Coavoux