Ich habe das Szenario, in dem Zeilen am Anfang und Ende der riesigen Dateien hinzugefügt werden.
Ich habe versucht, wie unten gezeigt.
für die erste Zeile:
sed -i '1i\'"$FirstLine" $Filename
für die letzte Zeile:
sed -i '$ a\'"$Lastline" $Filename
Das Problem bei diesem Befehl ist jedoch, dass die erste Zeile der Datei angehängt und die gesamte Datei durchlaufen wird. In der letzten Zeile wird erneut die gesamte Datei durchlaufen und eine letzte Zeile angehängt. Da es sich um eine sehr große Datei (14 GB) handelt, dauert dies sehr lange.
Wie kann ich am Anfang und am Ende einer Datei eine Zeile einfügen, während ich die Datei nur einmal lese?
quelle
for
Schleife:for file in Tes*; do [command]; done
"$file"
nichtTes*
als Argument verwenden mussted
.Beachten Sie, dass Sie Folgendes tun können, wenn Sie die Zuordnung einer vollständigen Kopie der Datei auf der Festplatte vermeiden möchten:
Dies nutzt die Tatsache, dass, wenn es sich bei stdin / stdout um eine Datei handelt,
sed
blockweise gelesen und geschrieben wird. Hier ist es also in Ordnung, die gelesene Datei zu überschreiben, solange die erste hinzugefügte Zeile kleiner alssed
die Blockgröße ist (sollte etwa 4k oder 8k sein).Beachten Sie jedoch, dass wenn aus irgendeinem Grund ein
sed
Fehler auftritt (Abbruch, Maschinenabsturz ...), die Datei zur Hälfte verarbeitet wird, was bedeutet, dass einige Daten der Größe der ersten Zeile irgendwo in der Mitte fehlen.Beachten Sie auch , dass , wenn Ihr
sed
ist die GNUsed
, die nicht Arbeit für binäre Daten (aber da Sie verwenden-i
, den Sie verwenden GNU sed).quelle
Hier sind einige Optionen (alle erstellen eine neue Kopie der Datei, stellen Sie also sicher, dass Sie genügend Speicherplatz dafür haben):
einfaches Echo / Katze
awk / gawk usw
awk
und sein Typ liest Dateien Zeile für Zeile. DerBEGIN{}
Satz wird vor der ersten Zeile und derEND{}
Satz nach der letzten Zeile ausgeführt. Also, der obige Befehl bedeutetprint "first" at the beginning, then print every line in the file and print "last" at the end
.Perl
Dies ist im Wesentlichen dasselbe wie der oben in Perl geschriebene Gawk.
quelle
sed -i
das temporäre Dateien erstellt.Ich bevorzuge das viel einfachere:
Dies transformiert die Datei:
zur Datei:
quelle
Sie können Vim im Ex-Modus verwenden:
1
erste Zeile auswähleni
Text und Zeilenumbruch einfügen$
Letzte Zeile auswählena
Text und Zeilenumbruch anhängenx
speichern und schließenquelle
Es gibt keine Möglichkeit, Daten am Anfang einer Datei einzufügen¹. Sie können lediglich eine neue Datei erstellen, die zusätzlichen Daten schreiben und die alten Daten anhängen. Sie müssen also mindestens einmal die gesamte Datei neu schreiben, um die erste Zeile einzufügen. Sie können die letzte Zeile jedoch anhängen, ohne die Datei neu zu schreiben.
Alternativ können Sie die beiden Befehle in einem Durchlauf von sed kombinieren.
sed -i
Erstellt eine neue Ausgabedatei und verschiebt sie dann über die alte Datei. Dies bedeutet, dass während der Arbeit von sed eine zweite Kopie der Datei vorhanden ist, die Speicherplatz belegt. Sie können dies vermeiden, indem Sie die vorhandene Datei überschreiben , jedoch mit erheblichen Einschränkungen: Die hinzugefügte Zeile muss kleiner sein als der Puffer von sed. Wenn Ihr System abstürzt, gehen eine beschädigte Datei und einige Inhalte in der Datei verloren Mitte, also empfehle ich dringend dagegen.¹ Linux kann zwar Daten in eine Datei einfügen, es können jedoch nur eine ganze Reihe von Dateisystemblöcken und keine Zeichenfolgen beliebiger Länge eingefügt werden. Es ist nützlich für einige Anwendungen, wie z. B. Datenbanken und virtuelle Maschinen, aber für Textdateien unbrauchbar.
quelle
fallocate()
mitFALLOC_FL_INSERT_RANGE
verfügbaren auf XFS und ext4 in modernen Kerneln (4.xx) man7.org/linux/man-pages/man2/fallocate.2.htmlquelle
Moderne Linux-Kernel (höher als 4.1 oder 4.2) unterstützen das Einfügen von Daten am Anfang einer Datei über den
fallocate()
Systemaufruf mit denFALLOC_FL_INSERT_RANGE
Dateisystemen ext4 und xfs. Im Wesentlichen ist dies eine logische Verschiebeoperation: Die Daten werden logisch mit einem höheren Versatz verschoben.Es gibt eine Einschränkung hinsichtlich der Granularität des Bereichs, den Sie am Anfang der Datei einfügen möchten. Aber für Textdateien können Sie wahrscheinlich etwas mehr als erforderlich zuweisen (bis zur Granularitätsgrenze) und mit Leerzeichen oder Zeilenumbrüchen füllen, aber das hängt von Ihrer Anwendung ab
Ich kenne kein sofort verfügbares Linux-Dienstprogramm, das Dateierweiterungen manipuliert, aber es ist nicht schwierig zu schreiben: Besorgen Sie sich einen Dateideskriptor und rufen Sie
fallocate()
mit den entsprechenden Argumenten auf. Weitere Informationen finden Sie in der Manpage desfallocate
Systemaufrufs: http://man7.org/linux/man-pages/man2/fallocate.2.htmlquelle
fallocate
Dienstprogramm. Das Problem ist, dass eine Granularität ganzer Blöcke dies für die meisten Textdateien unbrauchbar macht. Ein weiteres Problem besteht darin, dass die Bereichszuordnung und die anschließende Änderung nicht atomar sind. Das Problem ist hier also nicht wirklich gelöst.fallocate
Atomizität gebrochen ist, bitte, ich bin neugierig)