¿Extraer la sección central de líneas de un archivo de texto?

17

Estoy escribiendo un script PHP para analizar un archivo de texto grande para hacer inserciones de base de datos desde él. Sin embargo, en mi host, el archivo es demasiado grande y llegué al límite de memoria para PHP.

El archivo tiene aproximadamente 16,000 líneas; Quiero dividirlo en cuatro archivos separados (al principio) para ver si puedo cargarlos.

La primera parte con la que puedo llegar head -4000 file.txt. Las secciones del medio son un poco más complicadas: estaba pensando en canalizar la tailsalida a head( tail -4001 file.txt | head -4000 > section2.txt), pero ¿hay otra / mejor manera?

En realidad, mi lógica está en mal estado: para la sección dos, necesitaría algo así tail -12001 file.txt | head - 4000, y luego reducir el tailargumento para las siguientes secciones. Ya me estoy confundiendo! :PAG

usuario394
fuente

Respuestas:

27

Si no quiere equivocarse pero aún lo hace usando taily head, hay una forma útil de invocar tailusando un recuento de líneas desde el principio, no al final:

tail -n +4001 yourfile | head -4000

... Pero una mejor herramienta automática hecha solo para dividir archivos se llama ... split! También es parte de los coreutils de GNU, por lo que cualquier sistema Linux normal debería tenerlo. Así es como puedes usarlo:

split -l 4000 yourInputFile thePrefixForOutputFiles

(Ver man splitsi tiene dudas).

rozcietrzewiacz
fuente
19

Combinar cabeza y cola como lo hiciste funcionaría, pero para esto usaría sed

sed -n '1,4000p' input_file # print lines 1-4000 of input_file

Esto le permite resolver su problema con una función de shell rápida

chunk_it(){
    step=4
    start=1
    end=$step
    for n in {1..4} ; do
        sed -n "${start},${end}p" "$1" > "$1".$start-$end
        let start+=$step
        let end+=$step
    done
}

chunk_it your_file

Ahora tiene your_file.1-4000 y yuor_file.4001-8000 y así sucesivamente.

Nota: requiere bash

Sorpigal
fuente
3
Me gusta la forma sed.
fanchyna
Esto no funciona para mí porque sed no sale. Imprime las líneas que quiero stdout, pero tengo que ctrl-c, y como resultado, no puedo redirigirlo a un archivo. ¿Alguna sugerencia para que sea utilizable?
Brent212
¡Lo averigué! "sed -n '<start_line>, <end_line> w <output_file>' <input_file>" funciona para mí.
Brent212
@ Brent212 Otra opción a tener en cuenta es que también puede canalizarlo en menos o redirigir la salida a un archivo.
Kyle s