Unix - eine riesige .gz-Datei zeilenweise aufteilen

Unix - eine riesige .gz-Datei zeilenweise aufteilen

Ich bin sicher, dass jemand das folgende Bedürfnis schon einmal hatte: Wie kann man eine riesige .gz-Datei schnell zeilenweise aufteilen? Die zugrunde liegende Textdatei hat 120 Millionen Zeilen. Ich habe nicht genug Speicherplatz, um die gesamte Datei auf einmal zu komprimieren, also habe ich mich gefragt, ob jemand ein Bash-/Perl-Skript oder -Tool kennt, mit dem man die Datei (entweder die .gz- oder die innere .txt-Datei) in 3 Dateien mit 40 Millionen Zeilen aufteilen kann. Das könnte man zum Beispiel so aufrufen:

    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, mehrere davon auszuführen, oder würde gunzip -c genug Speicherplatz benötigen, um die gesamte Datei zu entpacken (also das ursprüngliche Problem): gunzip -c hugefile.txt.gz | head 4000000

Hinweis: Ich kann keine zusätzliche Festplatte bekommen.

Danke!

Antwort1

Wie Sie dabei am besten vorgehen, hängt von Ihren Wünschen ab:

  • Möchten Sie einen einzelnen Teil der großen Datei extrahieren?
  • Oder möchten Sie alle Teile in einem Rutsch erstellen?

Wenn Sie eineeinzelner Teil der Datei, Ihre Idee zu verwenden gunzipund headist richtig. Sie können verwenden:

gunzip -c hugefile.txt.gz | head -n 4000000

Dadurch würden die ersten 4.000.000 Zeilen über die Standardausgabe ausgegeben. Wahrscheinlich möchten Sie eine weitere Pipe anhängen, um tatsächlich etwas mit den Daten zu tun.

Um die anderen Teile zu erhalten, verwenden Sie eine Kombination aus headund tail, etwa:

gunzip -c hugefile.txt.gz | head -n 8000000 |tail -n 4000000

um den zweiten Block zu erhalten.

Ist es vielleicht eine Lösung, mehrere davon auszuführen, oder würde gunzip -c genug Speicherplatz benötigen, um die gesamte Datei zu entpacken?

Nein, dafür gunzip -cist kein Speicherplatz erforderlich. Der Vorgang wird im Speicher ausgeführt und anschließend auf die Standardausgabe gestreamt.


Wenn Sie erstellen möchtenalle Teile auf einmal, es ist effizienter, sie alle mit einem einzigen Befehl zu erstellen, da die Eingabedatei dann nur einmal gelesen wird. Eine gute Lösung ist die Verwendung von split; Einzelheiten finden Sie in der Antwort von Jim McNamara.

Antwort2

Um die Pipe zu teilen, verwenden Sie entweder gunzip -c oder zcat, um die Datei zu öffnen

gunzip -c bigfile.gz | split -l 400000

Fügen Sie dem Split-Befehl Ausgabespezifikationen hinzu.

Antwort3

Da Sie an einem (nicht zurückspulbaren) Stream arbeiten, möchten Sie die „+N“-Form des Endes verwenden, um Zeilen ab Zeile N zu erhalten.

zcat hugefile.txt.gz | head -n 40000000
zcat hugefile.txt.gz | tail -n +40000001 | head -n 40000000
zcat hugefile.txt.gz | tail -n +80000001 | head -n 40000000

Antwort4

.gz-Datei direkt in .gz-Dateien aufteilen:

zcat bigfile.gz | split -l 400000 --filter='gzip > $FILE.gz'

Ich denke, das ist es, was OP wollte, weil er nicht viel Platz hat.

verwandte Informationen