Antworten:
Versuchen Sie ed
stattdessen:
ed <<< $'1d\nwq' large_file
Wenn dieses "große" etwa 10 Millionen Zeilen oder mehr bedeutet, sollten Sie es besser verwenden tail
. Ist nicht in der Lage, direkt zu bearbeiten, aber seine Leistung macht dies unverzeihlich:
tail -n +2 large_file > large_file.new
Bearbeiten , um einige Zeitunterschiede anzuzeigen :
( awk
Code von Jaypal hinzugefügt, um Ausführungszeiten auf demselben Computer zu haben (CPU 2.2GHz).)
bash-4.2$ seq 1000000 > bigfile.txt # further file creations skipped
bash-4.2$ time sed -i 1d bigfile.txt
time 0m4.318s
bash-4.2$ time ed -s <<< $'1d\nwq' bigfile.txt
time 0m0.533s
bash-4.2$ time perl -pi -e 'undef$_ if$.==1' bigfile.txt
time 0m0.626s
bash-4.2$ time { tail -n +2 bigfile.txt > bigfile.new && mv -f bigfile.new bigfile.txt; }
time 0m0.034s
bash-4.2$ time { awk 'NR>1 {print}' bigfile.txt > newfile.txt && mv -f newfile.txt bigfile.txt; }
time 0m0.328s
awk
und bekam das folgende Ergebnis -[jaypal:~/Temp] seq 1000000 > bigfile.txt [jaypal:~/Temp] time awk 'NR>1 {print}' bigfile.txt >newfile.txt real 0m0.649s user 0m0.601s sys 0m0.033s
awk
die Leistung näher an sed
der von liegt. (Anmerkung für mich: Niemals erwarten - stattdessen testen.)
tail -n +2 bigfile.txt > bigfile.new && mv -f bigfile.new bigfile.txt;
Ich verwende eine einzelne Datei mit einer Sperre, um eine einzelne Aufgabenliste zu verfolgen, die von mehreren Prozessen verwendet wird. Ich begann mit dem, was die ursprüngliche Plakat verwendet: sed -i 1d large_file
. Dadurch wurde die Datei für 1-2 Sekunden gesperrt. Die tail/mv
Kombo wird fast augenblicklich beendet. Vielen Dank!
Es gibt keine Möglichkeit, Dinge effizient vom Anfang einer Datei zu entfernen. Um Daten von Anfang an zu entfernen, muss die gesamte Datei neu geschrieben werden.
Das Abschneiden vom Ende einer Datei kann jedoch sehr schnell gehen (das Betriebssystem muss nur die Dateigrößeninformationen anpassen und möglicherweise nicht verwendete Blöcke löschen). Dies ist im Allgemeinen nicht möglich, wenn Sie versuchen, eine Datei aus dem Kopf zu entfernen.
Es könnte theoretisch "schnell" sein, wenn Sie einen ganzen Block / eine ganze Ausdehnung genau entfernt haben, aber dafür gibt es keine Systemaufrufe, sodass Sie sich auf die dateisystemspezifische Semantik verlassen müssten (falls vorhanden). (Oder ich habe eine Art Offset innerhalb des ersten Blocks / der ersten Ausdehnung, um den tatsächlichen Dateianfang zu markieren. Ich habe auch noch nie davon gehört.)
Die effizienteste Methode, tu es nicht! In jedem Fall benötigen Sie doppelt so viel Speicherplatz auf der Festplatte und verschwenden E / A-Vorgänge.
Wenn Sie mit einer großen Datei nicht weiterkommen, die Sie ohne die erste Zeile lesen möchten, warten Sie, bis Sie sie zum Entfernen der ersten Zeile lesen müssen. Wenn Sie die Datei von stdin an ein Programm senden müssen, verwenden Sie tail, um dies zu tun:
tail -n +2 | your_program
Wenn Sie die Datei lesen müssen, können Sie die erste Zeile entfernen, jedoch nur, wenn Sie über den erforderlichen Speicherplatz auf der Festplatte verfügen:
tail -n +2 | tee large_file2 | your_program
Wenn Sie nicht von stdin lesen können, verwenden Sie ein Fifo:
mkfifo large_file_wo_1st_line
tail -n +2 large_file > large_file_wo_1st_line&
your_program -i large_file_wo_1st_line
Umso besser, wenn Sie bash verwenden, können Sie die Prozessersetzung nutzen:
your_program -i <(tail -n +2 large_file)
Wenn Sie in der Datei suchen müssen, sehe ich keine bessere Lösung, als nicht an erster Stelle mit der Datei stecken zu bleiben. Wenn diese Datei von stdout generiert wurde:
large_file_generator | tail -n +2 > large_file
Ansonsten gibt es immer die FIFO- oder Prozesssubstitutionslösung:
mkfifo large_file_with_1st_file
large_file_generator -o large_file_with_1st_file&
tail -n +2 large_file_with_1st_file > large_file_wo_1st_file
large_file_generator -o >(tail -n 2+ > large_file_wo_1st_file)
Sie können Vim im Ex-Modus verwenden:
ex -sc '1d|x' large_file
1
erste Zeile auswählen
d
löschen
x
speichern und schließen
Das ist nur theoretisch, aber ...
Ein benutzerdefiniertes Dateisystem (implementiert mit FUSE oder einem ähnlichen Mechanismus) kann ein Verzeichnis verfügbar machen, dessen Inhalt genau mit dem eines bereits vorhandenen Verzeichnisses an einer anderen Stelle übereinstimmt, dessen Dateien jedoch nach Belieben gekürzt werden. Das Dateisystem würde alle Datei-Offsets übersetzen. Dann müssten Sie eine Datei nicht zeitaufwändig umschreiben.
Angesichts der Tatsache, dass diese Idee nicht trivial ist, wäre die Implementierung eines solchen Dateisystems zu teuer / zeitaufwendig, um praktisch zu sein, es sei denn, Sie haben Dutzende von Terabytes solcher Dateien.
tail
würde zähle ich eher die Zeit zu tun , sowohl die erste Zeile zu entfernen und ersetzenbigfile.txt
mitbigfile.new
.