Puede que esta no sea la forma más eficiente, pero funciona:
shuf <file> > tmp
head -n $m tmp > out1
tail -n +$(( m + 1 )) tmp > out2
Con $m
que contiene el número de líneas.
Este script bash/awk elige líneas al azar y mantiene la secuencia original en ambos archivos de salida.
awk -v m=4 -v N=$(wc -l <file) -v out1=/tmp/out1 -v out2=/tmp/out2 \
'BEGIN{ srand()
do{ lnb = 1 + int(rand()*N)
if ( !(lnb in R) ) {
R[lnb] = 1
ct++ }
} while (ct<m)
} { if (R[NR]==1) print > out1
else print > out2
}' file
cat /tmp/out1
echo ========
cat /tmp/out2
Salida, basada en los datos de la pregunta.
12345
23456
200
600
========
67891
-20000
20
Como con todas las cosas de Unix, hay una utilidad para eso.
Programa del día:split
split
dividirá un archivo de muchas maneras diferentes, -b
bytes, -l
líneas, -n
número de archivos de salida. Usaremos el -l
opción. Dado que desea elegir líneas aleatorias y no solo la primera m
, sort
el archivo al azar primero. Si quieres leer sobre sort
, consulta mi respuesta aquí.
Ahora, el código real. Es bastante simple, en realidad:
sort -R input_file | split -l $m output_prefix
Esto creará dos archivos, uno con m
líneas y una con N-m
líneas, llamadas output_prefixaa
y output_prefixab
.Asegúrate de m
es el archivo más grande que desea o obtendrá varios archivos de longitud m
(y uno con N % m
).
Si quiere asegurarse de usar el tamaño correcto, aquí hay un pequeño código para hacerlo:
m=10 # size you want one file to be
N=$(wc -l input_file)
m=$(( m > N/2 ? m : N - m ))
sort -R input_file | split -l $m output_prefix
Editar:me ha llamado la atención que algunos sort
las implementaciones no tienen un -R
bandera. Si tienes perl
, puede sustituir perl -e 'use List::Util qw/shuffle/; print shuffle <>;'
.