I want to do the inverse of sort(1) : randomize every line of stdin to stdout in Perl.
This perl snippet does the trick :
#! /usr/bin/perl
# randomize cat
# fisher_yates_shuffle code copied from Perl Cookbook
# (By Tom Christiansen & Nathan Torkington; ISBN 1-56592-243-3)
use strict;
my @lines = <>;
fisher_yates_shuffle( \@lines ); # permutes @array in place
foreach my $line (@lines) {
print $line;
}
# fisher_yates_shuffle( \@array ) : generate a random permutation
# of @array in place
sub fisher_yates_shuffle {
my $array = shift;
my $i;
for ($i = @$array; --$i; ) {
my $j = int rand ($i+1);
next if $i == $j;
@$array[$i,$j] = @$array[$j,$i];
}
}
__END__
I bet real Perl hackers will tear this apart, but here it goes nonetheless.
use strict;
use warnings;
use List::Util 'shuffle';
my @lines = ();
my $bufsize = 512;
while(<STDIN>) {
push @lines, $_;
if (@lines == $bufsize) {
print shuffle(@lines);
undef @lines;
}
}
print shuffle(@lines);
Difference between this and the other solution:
use List::Util 'shuffle';
print shuffle <>
Or if you worry about last lines lacking \n,
chomp(my @lines = <>);
print "$_\n" for shuffle @lines;