Ce n'est peut-être pas le moyen le plus efficace, mais cela fonctionne :
shuf <file> > tmp
head -n $m tmp > out1
tail -n +$(( m + 1 )) tmp > out2
Avec $m
contenant le nombre de lignes.
Ce script bash/awk choisit des lignes au hasard et conserve la séquence d'origine dans les deux fichiers de sortie.
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
Sortie, basée sur les données de la question.
12345
23456
200
600
========
67891
-20000
20
Comme pour tout ce qui concerne Unix, il y a un utilitaire pour ça.
Programme du jour :split
split
divisera un fichier de différentes manières, -b
octets, -l
lignes, -n
nombre de fichiers de sortie. Nous utiliserons le -l
option. Puisque vous voulez choisir des lignes aléatoires et pas seulement les premières m
, nous allons sort
le fichier au hasard en premier. Si vous voulez en savoir plus sur sort
, reportez-vous à ma réponse ici.
Maintenant, le code réel. C'est assez simple, vraiment :
sort -R input_file | split -l $m output_prefix
Cela fera deux fichiers, un avec m
lignes et une avec N-m
lignes, nommées output_prefixaa
et output_prefixab
.Assurez-vous que m
est le plus gros fichier que vous voulez ou vous obtiendrez plusieurs fichiers de longueur m
(et un avec N % m
).
Si vous voulez vous assurer que vous utilisez la bonne taille, voici un petit code pour le faire :
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
Edit :Il a été porté à mon attention que certains sort
les implémentations n'ont pas de -R
drapeau. Si vous avez perl
, vous pouvez remplacer perl -e 'use List::Util qw/shuffle/; print shuffle <>;'
.