¿Cómo dividir un archivo de texto grande en archivos más pequeños con igual cantidad de líneas?

Tengo un gran archivo de texto plano (por número de líneas) que me gustaría dividir en archivos más pequeños, también por número de líneas. Entonces, si mi archivo tiene alrededor de 2M líneas, me gustaría dividirlo en 10 archivos que contienen 200k líneas, o 100 archivos que contienen 20k líneas (más un archivo con el rest, ser igual de divisible no importa).

Podría hacer esto bastante fácilmente en Python, pero me pregunto si hay algún tipo de forma ninja para hacer esto usando utilidades bash y unix (a diferencia de las líneas de looping y recuento / división de forma manual).

¿Has mirado el comando dividir?

 $ split --help Usage: split [OPTION] [INPUT [PREFIX]] Output fixed-size pieces of INPUT to PREFIXaa, PREFIXab, ...; default size is 1000 lines, and default PREFIX is `x'. With no INPUT, or when INPUT is -, read standard input. Mandatory arguments to long options are mandatory for short options too. -a, --suffix-length=N use suffixes of length N (default 2) -b, --bytes=SIZE put SIZE bytes per output file -C, --line-bytes=SIZE put at most SIZE bytes of lines per output file -d, --numeric-suffixes use numeric suffixes instead of alphabetic -l, --lines=NUMBER put NUMBER lines per output file --verbose print a diagnostic to standard error just before each output file is opened --help display this help and exit --version output version information and exit 

Podrías hacer algo como esto:

 split -l 200000 filename 

que creará archivos cada uno con 200000 líneas llamadas xaa xab xac

Otra opción, dividida por el tamaño del archivo de salida (aún se divide en saltos de línea):

  split -C 20m --numeric-suffixes input_filename output_prefix 

crea archivos como output_prefix01 output_prefix02 output_prefix03 ... cada uno de un tamaño máximo de 20 megabytes.

¿Qué tal el comando dividir ?

 split -l 200000 mybigfile.txt 

Sí, hay un comando split . Se dividirá un archivo por líneas o bytes.

 $ split --help Usage: split [OPTION]... [INPUT [PREFIX]] Output fixed-size pieces of INPUT to PREFIXaa, PREFIXab, ...; default size is 1000 lines, and default PREFIX is `x'. With no INPUT, or when INPUT is -, read standard input. Mandatory arguments to long options are mandatory for short options too. -a, --suffix-length=N use suffixes of length N (default 2) -b, --bytes=SIZE put SIZE bytes per output file -C, --line-bytes=SIZE put at most SIZE bytes of lines per output file -d, --numeric-suffixes use numeric suffixes instead of alphabetic -l, --lines=NUMBER put NUMBER lines per output file --verbose print a diagnostic just before each output file is opened --help display this help and exit --version output version information and exit SIZE may have a multiplier suffix: b 512, kB 1000, K 1024, MB 1000*1000, M 1024*1024, GB 1000*1000*1000, G 1024*1024*1024, and so on for T, P, E, Z, Y. 

usar split

Divida un archivo en piezas de tamaño fijo, cree archivos de salida que contengan secciones consecutivas de INPUT (entrada estándar si no se proporciona ninguna o INPUT es `- ‘)

Syntax split [options] [INPUT [PREFIX]]

http://ss64.com/bash/split.html

Utilizar:

 sed -n '1,100p' filename > output.txt 

Aquí, 1 y 100 son los números de línea que capturará en output.txt .

también puedes usar awk

 awk -vc=1 'NR%200000==0{++c}{print $0 > c".txt"}' largefile 

divide el archivo “file.txt” en archivos de 10000 líneas:

 split -l 10000 file.txt 

En caso de que solo quiera dividir por x número de líneas cada archivo, las respuestas dadas acerca de la split son correctas. Pero tengo curiosidad de que nadie haya prestado atención a los requisitos:

  • “sin tener que contarlos” -> usando wc + cut
  • “tener el rest en el archivo adicional” -> división hace por defecto

No puedo hacer eso sin “wc + cut”, pero lo estoy usando:

 split -l $(expr `wc $filename | cut -d ' ' -f3` / $chunks) $filename 

Esto se puede agregar fácilmente a sus funciones de bashrc para que pueda invocarlo pasando nombre de archivo y fragmentos:

  split -l $(expr `wc $1 | cut -d ' ' -f3` / $2) $1 

En caso de que desee solo x fragmentos sin rest en un archivo adicional, simplemente adapte la fórmula para sumrlo (fragmentos – 1) en cada archivo. Utilizo este enfoque porque generalmente solo quiero x cantidad de archivos en lugar de x líneas por archivo:

 split -l $(expr `wc $1 | cut -d ' ' -f3` / $2 + `expr $2 - 1`) $1 

Puede agregar eso a un script y llamarlo su “camino ninja”, porque si nada satisface sus necesidades, puede comstackrlo 🙂

split (de GNU coreutils, desde la versión 8.8 de 2010-12-22 ) incluye el siguiente parámetro:

 -n, --number=CHUNKS generate CHUNKS output files; see explanation below CHUNKS may be: N split into N files based on size of input K/N output Kth of N to stdout l/N split into N files without splitting lines/records l/K/N output Kth of N to stdout without splitting lines/records r/N like 'l' but use round robin distribution r/K/N likewise but only output Kth of N to stdout 

Por lo tanto, split -n 4 input output. generará cuatro archivos ( output.a{a,b,c,d} ) con la misma cantidad de bytes, pero las líneas podrían estar rotas en el medio.

Si queremos preservar las líneas completas (es decir, dividir por líneas), entonces esto debería funcionar:

 split -nl/4 input output. 

Respuesta relacionada: https://stackoverflow.com/a/19031247

HDFS getmerge archivo pequeño y se derramó en el tamaño de la propiedad.

Este método causará un salto de línea

split -b 125m compact.file -d -a 3 compact_prefix

Intento fusionarme y dividirme en aproximadamente 128MB cada archivo.

dividido en 128m, la unidad de tamaño del juez es M o G, por favor prueba antes de usar.

 begainsize=`hdfs dfs -du -s -h /externaldata/$table_name/$date/ | awk '{ print $1}' ` sizeunit=`hdfs dfs -du -s -h /externaldata/$table_name/$date/ | awk '{ print $2}' ` if [ $sizeunit = "G" ];then res=$(printf "%.f" `echo "scale=5;$begainsize*8 "|bc`) else res=$(printf "%.f" `echo "scale=5;$begainsize/128 "|bc`) # celling ref http://blog.csdn.net/naiveloafer/article/details/8783518 fi echo $res # split into $res files with number suffix. ref http://blog.csdn.net/microzone/article/details/52839598 compact_file_name=$compact_file"_" echo "compact_file_name :"$compact_file_name split -nl/$res $basedir/$compact_file -d -a 3 $basedir/${compact_file_name}