Ich bin sicher, dass jemand die folgenden Anforderungen hatte. Was ist ein schneller Weg, um eine riesige .gz-Datei zeilenweise aufzuteilen? Die zugrunde liegende Textdatei enthält 120 Millionen Zeilen. Ich habe nicht genügend Speicherplatz, um die gesamte Datei auf einmal zu komprimieren. Ich habe mich gefragt, ob jemand ein Bash / Perl-Skript oder -Tool kennt, mit dem die Datei (entweder die .gz-Datei oder die innere .txt-Datei) in 3x 40mn-Zeilendateien aufgeteilt werden kann . zB wie es heißt:
bash splitter.sh hugefile.txt.gz 4000000 1
would get lines 1 to 40 mn
bash splitter.sh hugefile.txt.gz 4000000 2
would get lines 40mn to 80 mn
bash splitter.sh hugefile.txt.gz 4000000 3
would get lines 80mn to 120 mn
Ist es vielleicht eine Lösung, eine Reihe dieser Probleme zu lösen, oder würde das gunzip -c genügend Speicherplatz benötigen, um die gesamte Datei zu entpacken (dh das ursprüngliche Problem): gunzip -c hugefile.txt.gz | Kopf 4000000
Hinweis: Ich kann keine zusätzliche Festplatte beschaffen.
Vielen Dank!
Antworten:
Wie dies am besten funktioniert, hängt davon ab, was Sie möchten:
Wenn Sie einen einzelnen Teil der Datei möchten , ist Ihre Idee zu verwenden
gunzip
undhead
richtig. Sie können verwenden:Das würde die ersten 4000000 Zeilen bei Standardausgabe ausgeben - Sie möchten wahrscheinlich eine weitere Pipe anhängen, um tatsächlich etwas mit den Daten zu tun.
Um die anderen Teile zu erhalten, würden Sie eine Kombination aus
head
und verwendentail
, wie:um den zweiten Block zu bekommen.
Nein, der
gunzip -c
benötigt keinen Speicherplatz - er erledigt alles im Speicher und überträgt es dann auf stdout.Wenn Sie alle Teile auf einmal erstellen möchten , ist es effizienter , alle Teile mit einem einzigen Befehl zu erstellen, da die Eingabedatei dann nur einmal gelesen wird. Eine gute Lösung ist zu verwenden
split
; Weitere Informationen finden Sie in der Antwort von Jim Mcnamara.quelle
gzip
kennt das Limit nicht (was aus einem anderen Prozess stammt). Wennhead
verwendet,head
wird beendet, wenn es genug empfangen hat, und dies wird sich ausbreitengzip
(über SIGPIPE, siehe Wikipedia). Datail
dies nicht möglich ist, wird jagzip
alles dekomprimiert.Pipe zum Teilen verwenden Sie entweder gunzip -c oder zcat, um die Datei zu öffnen
Fügen Sie dem Befehl split Ausgabespezifikationen hinzu.
quelle
Wenn Sie an einem Stream (der nicht zurückgespult werden kann) arbeiten, möchten Sie die Endform '+ N' verwenden, um Zeilen ab Zeile N zu erhalten.
quelle
Ich würde Split in Betracht ziehen .
quelle
GZ-Datei direkt in GZ-Dateien aufteilen:
Ich denke, das ist es, was OP wollte, weil er nicht viel Platz hat.
quelle
Hier ist ein Python-Skript, mit dem Sie eine globale Gruppe von Dateien aus einem Verzeichnis öffnen, diese bei Bedarf komprimieren und zeilenweise durchlesen können. Es wird nur der Speicherplatz verwendet, der zum Speichern der Dateinamen und der aktuellen Zeile erforderlich ist, plus ein wenig Overhead.
Der Befehl print line sendet jede Zeile an std out, sodass Sie in eine Datei umleiten können. Wenn Sie uns aber auch mitteilen, was Sie mit den Zeilen tun möchten, kann ich es dem Python-Skript hinzufügen, und Sie müssen keine Teile der Datei herumliegen lassen.
quelle
Hier ist ein Perl-Programm, mit dem Sie stdin lesen und die Zeilen teilen können. Dabei wird jeder Clump an einen separaten Befehl weitergeleitet, der mithilfe der Shell-Variablen $ SPLIT an ein anderes Ziel weitergeleitet werden kann. Für Ihren Fall würde es mit aufgerufen werden
zcat hugefile.txt.gz | perl xsplit.pl 40000000 'cat > tmp$SPLIT.txt; do_something tmp$SPLIT.txt; rm tmp$SPLIT.txt'
Tut mir leid, die Befehlszeilenverarbeitung ist ein wenig kompliziert, aber Sie haben die Idee.
quelle