Ini mungkin bukan cara yang paling efisien tetapi berhasil:
shuf <file> > tmp
head -n $m tmp > out1
tail -n +$(( m + 1 )) tmp > out2
Dengan $m
berisi jumlah baris.
Skrip bash/awk ini memilih baris secara acak, dan mempertahankan urutan asli di kedua file keluaran.
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
Keluaran, berdasarkan data dalam pertanyaan.
12345
23456
200
600
========
67891
-20000
20
Seperti semua hal tentang Unix, Ada Utilitas untuk Itu.
Program hari ini:split
split
akan membagi file dengan berbagai cara, -b
byte, -l
baris, -n
jumlah file keluaran. Kami akan menggunakan -l
pilihan. Karena Anda ingin memilih baris acak dan bukan hanya m
pertama , kami akan sort
file secara acak terlebih dahulu. Jika Anda ingin membaca tentang sort
, lihat jawaban saya di sini.
Sekarang, kode sebenarnya. Ini cukup sederhana, sungguh:
sort -R input_file | split -l $m output_prefix
Ini akan membuat dua file, satu dengan m
baris dan satu dengan N-m
baris, bernama output_prefixaa
dan output_prefixab
.Pastikan m
adalah file yang lebih besar yang Anda inginkan atau Anda akan mendapatkan beberapa file dengan panjang m
(dan satu dengan N % m
).
Jika Anda ingin memastikan bahwa Anda menggunakan ukuran yang benar, berikut sedikit kode untuk melakukannya:
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
Sunting:Telah menjadi perhatian saya bahwa beberapa sort
implementasi tidak memiliki -R
bendera. Jika Anda memiliki perl
, Anda dapat mengganti perl -e 'use List::Util qw/shuffle/; print shuffle <>;'
.