Antworten:
Der Grund, warum file.txt nach diesem Befehl leer ist, ist die Reihenfolge, in der die Shell die Dinge tut. Das erste, was mit dieser Leitung passiert, ist die Umleitung. Die Datei "file.txt" wird geöffnet und auf 0 Byte gekürzt. Danach wird der Befehl sed ausgeführt, aber zu diesem Zeitpunkt ist die Datei bereits leer.
Es gibt einige Optionen, die meisten beinhalten das Schreiben in eine temporäre Datei.
sed '1d' file.txt > tmpfile; mv tmpfile file.txt # POSIX
sed -i '1d' file.txt # GNU sed only, creates a temporary file
perl -ip -e '$_ = undef if $. == 1' file.txt # also creates a temporary file
ed
.
ed
Befehl wäre: printf "%s\n" 1d w q | ed file.txt
(I heart ed)
-exec sed -i '1d' {} \;
Eine sehr leichte Alternative besteht darin, alles außer der ersten Zeile "abzuschneiden" (dies kann eine einfache Möglichkeit sein, Dateikopfzeilen im Allgemeinen zu entfernen):
# -n +2 : start at line 2 of the file.
tail -n +2 file.txt > file.stdout
Im Anschluss an @Evan Teitelman können Sie:
tail -n +2 file.txt | sponge file.txt
So vermeiden Sie eine temporäre Datei. Eine andere Option könnte sein:
echo "$(tail -n +2 file.txt)" > file.txt
Und so weiter. Letzten testen:
[user@work ~]$ cat file.txt
line 1
line 2
line 3
line 4
line 5
[user@work ~]$ echo "$(tail -n +2 file.txt)" > file.txt
[user@work ~]$ cat file.txt
line 2
line 3
line 4
line 5
[user@work ~]$
Hoppla, wir haben eine neue Zeile verloren (per @ 1_CR-Kommentar unten). Versuchen Sie stattdessen Folgendes:
printf "%s\n\n" "$(tail -n +2 file.txt)" > file.txt
[user@work ~]$ cat file.txt
line 1
line 2
line 3
line 4
line 5
[user@work ~]$ printf '%s\n\n' "$(tail -n +2 file.txt)" > file.txt
[user@work ~]$ cat file.txt
line 2
line 3
line 4
line 5
[user@work ~]$
Kommen Sie zurück zu sed und versuchen Sie:
printf '%s\n\n' "$(sed '1d' file.txt)" > file.txt
oder vielleicht
echo -e "$(sed '1d' file.txt)\n" > file.txt
Nebenwirkungen zu vermeiden.
tail
Trick hat bei mir funktioniert (hat bei einer 130-MB-Datei weniger als 3 Sekunden gedauert). Vielen Dank!
echo "$(tail -n +2 file.txt)" > file.txt
ist die perfekte Antwort.
Schauen Sie sich auch sponge
von an
moreutils
. sponge
Hält Daten von der Standardeingabe ein, bis das Schreibende der Standardeingabe geschlossen wird, bevor in eine Datei geschrieben wird. Es wird so verwendet:
sed '1d' file.txt | sponge file.txt
Da dieses Thema von Interesse ist, teste ich den Benchmark auf drei Arten:
sed '1d' d.txt > tmp.txt
tail -n +2 d.txt > tmp.txt
sed -i '1d' d.txt
Beachten Sie, dass das Ziel d.txt
eine 5,4-GB-Datei ist
Erhalten Sie das Ergebnis:
run 1 : sed '1d' d.txt > r1.txt
14s
run 2 : tail -n +2 d.txt > r2.txt
20s
run 3 : sed -i '1d' d.txt
88s
Fazit: Es scheint unten der schnellste Weg zu sein:
sed '1d' file.txt > tmpfile; mv tmpfile file.txt
sed '1d' d.txt
Methode enthielt den mv
Befehl nicht (so scheint es, als würde sie Ihre Tests lesen) . In meinen Tests auf FreeBSD mit einer 20MB-Datei sed -i
war das am schnellsten.
ex
kann für die direkte Bearbeitung ohne temporäre Datei verwendet werden
ex -c ':1d' -c ':wq' file.txt
strace -e open ex -c ':1d' -c ':wq' foo
. ex schneidet die Originaldatei mit der temporären Datei ab, wobei die Option -i von GNU sed das Original mit der temporären Datei überschreibt. Ich bin mir nicht sicher, wie BSD sed funktioniert.
Sie können Vim im Ex-Modus verwenden:
ex -s -c '1d|x' file.txt
1
Erste Zeile finden
d
löschen
x
speichern und schließen
Dieser Befehl entfernt 1 Zeile und speichert als "file.txt".
sed '1d' file.txt > /tmp/file.txt && mv /tmp/file.txt file.txt || rm -f /tmp/file.txt
So löschen Sie eine Praticiler-Zeile in einer Datei
Sed '1d' Datei
Sed '1d3d' Datei
Zeichen in Zeile löschen
1 Löschen Sie die ersten beiden Charter in lin
Sed 's /^..//' Datei
2 Löschen Sie die letzten beiden Zeilen
Sed 's / .. £ //' Datei
3 Leerzeile löschen
Sed '/ ^ £ / d' Datei
£
≠ $
.
Könnte vim verwenden, um dies zu tun:
vim -u NONE +'1d' +wq! /tmp/test.txt
Katze file01 | sed -e '1,3d'
// zeige Inhalt in file01 aber entferne die erste und dritte Zeile
sed
können Sie verwendensed -i .bak '1d' file.txt
.