Unix: divide un archivo .gz enorme por línea

Unix: divide un archivo .gz enorme por línea

Estoy seguro de que alguien ha tenido la siguiente necesidad: ¿cuál es una forma rápida de dividir un archivo .gz enorme por línea? El archivo de texto subyacente tiene 120 millones de filas. No tengo suficiente espacio en disco para comprimir todo el archivo a la vez, así que me preguntaba si alguien conoce algún script o herramienta bash/perl que pueda dividir el archivo (ya sea .gz o .txt interno) en 3 archivos de 40 minutos de línea. . es decir, llamándolo así:

    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

Quizás hacer una serie de estos sea una solución o gunzip -c requeriría suficiente espacio para descomprimir todo el archivo (es decir, el problema original): gunzip -c hugefile.txt.gz | cabeza 4000000

Nota: no puedo obtener un disco adicional.

¡Gracias!

Respuesta1

La mejor forma de hacerlo depende de lo que quieras:

  • ¿Quieres extraer una sola parte del archivo grande?
  • ¿O quieres crear todas las piezas de una sola vez?

Si quieres ununa sola parte del archivo, tu idea de usar gunzipy heades correcta. Puedes usar:

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

Eso generaría las primeras 4000000 líneas en la salida estándar; probablemente desee agregar otra tubería para hacer algo con los datos.

Para obtener las otras partes, usarías una combinación de heady tail, como:

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

para conseguir el segundo bloque.

¿Quizás hacer una serie de estos sea una solución o gunzip -c requeriría suficiente espacio para descomprimir todo el archivo?

No, gunzip -cno requiere espacio en disco: hace todo en la memoria y luego lo transmite a la salida estándar.


Si quieres creartodas las partes de una vez, es más eficiente crearlos todos con un solo comando, porque entonces el archivo de entrada solo se lee una vez. Una buena solución es utilizar split; consulte la respuesta de Jim Mcnamara para obtener más detalles.

Respuesta2

tubería para dividir use gunzip -c o zcat para abrir el archivo

gunzip -c bigfile.gz | split -l 400000

Agregue especificaciones de salida al comando de división.

Respuesta3

Mientras trabaja en una secuencia (no rebobinable), querrá utilizar la forma de cola '+N' para obtener líneas que comiencen desde la línea N en adelante.

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

Respuesta4

Divida directamente el archivo .gz en archivos .gz:

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

Creo que esto es lo que quería OP, porque no tiene mucho espacio.

información relacionada