Wenn es Ihnen nichts ausmacht, die Zeilen neu zu ordnen, und Sie GNU-Coreutils haben (dh auf nicht eingebettetem Linux oder Cygwin, das seit shuf
Version 6.0 nicht zu alt ist ), shuf
ordnet („shuffle“) die Zeilen einer Datei nach dem Zufallsprinzip neu. So können Sie die Datei mischen und die ersten m Zeilen in eine Datei und den Rest in eine andere Datei verschieben.
Es gibt keine ideale Möglichkeit, diesen Versand durchzuführen. Man kann nicht einfach verketten head
und würde tail
da head
vorne puffern. Sie können verwenden split
, aber Sie erhalten keine Flexibilität in Bezug auf die Ausgabedateinamen. Sie können awk
natürlich verwenden:
<input shuf | awk -v m=$m '{ if (NR <= m) {print >"output1"} else {print} }'
Sie können verwenden sed
, was für große Dateien unklar, aber möglicherweise schneller ist.
<input shuf | sed -e "1,${m} w output1" -e "1,${m} d" >output2
Oder Sie können verwenden tee
, um die Daten zu duplizieren, wenn Ihre Plattform hat /dev/fd
; das ist ok wenn m klein ist:
<input shuf | { tee /dev/fd/3 | head -n $m >output1; } 3>&1 | tail -n +$(($m+1)) >output2
Portabel können Sie awk verwenden, um jede Zeile der Reihe nach zu versenden. Beachten Sie, dass awk nicht sehr gut darin ist, seinen Zufallszahlengenerator zu initialisieren. Die Zufälligkeit ist nicht nur definitiv nicht für die Kryptographie geeignet, sondern auch nicht sehr gut für numerische Simulationen. Der Startwert ist für alle awk-Aufrufe auf jedem System in einem Zeitraum von einer Sekunde gleich.
<input awk -v N=$(wc -l <input) -v m=3 '
BEGIN {srand()}
{
if (rand() * N < m) {--m; print >"output1"} else {print >"output2"}
--N;
}'
Wenn Sie eine bessere Zufälligkeit benötigen, können Sie dasselbe in Perl tun, in dem der RNG-Wert ordnungsgemäß festgelegt wird.
<input perl -e '
open OUT1, ">", "output1" or die $!;
open OUT2, ">", "output2" or die $!;
my $N = `wc -l <input`;
my $m = $ARGV[0];
while (<STDIN>) {
if (rand($N) < $m) { --$m; print OUT1 $_; } else { print OUT2 $_; }
--$N;
}
close OUT1 or die $!;
close OUT2 or die $!;
' 42