これは最も効率的な方法ではないかもしれませんが、うまくいきます:
shuf <file> > tmp
head -n $m tmp > out1
tail -n +$(( m + 1 )) tmp > out2
$m
で 行数を含みます。
この bash/awk スクリプトは行をランダムに選択し、両方の出力ファイルで元のシーケンスを維持します。
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
質問のデータに基づいて出力します。
12345
23456
200
600
========
67891
-20000
20
すべての Unix と同様に、そのためのユーティリティがあります。
今日のプログラム:split
split
さまざまな方法でファイルを分割します -b
バイト、-l
行、-n
出力ファイルの数。 -l
を使用します オプション。最初の m
だけでなく、ランダムな行を選択したいので 、sort
最初にファイルをランダムに。 sort
について読みたい場合 、ここで私の回答を参照してください。
では、実際のコードです。本当に簡単です:
sort -R input_file | split -l $m output_prefix
これにより、2 つのファイルが作成され、1 つには m
が含まれます。 行と N-m
の行 output_prefixaa
という名前の行 と output_prefixab
.必ず m
または、長さ m
の複数のファイルを取得します。 (および N % m
の 1 つ )。
正しいサイズを確実に使用したい場合は、それを行うための小さなコードを次に示します:
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
編集:いくつかの sort
が私の注意を引きました 実装には -R
がありません 国旗。 perl
がある場合 、 perl -e 'use List::Util qw/shuffle/; print shuffle <>;'
に置き換えることができます .