How can I print the lines in STDIN in random order in Perl?
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:
- Will not consume all the input and then randomize it (memory hog), but will randomize every $bufsize lines (not truly random and slow as a dog compared to the other option).
- Uses a module which returns a new list instead of a in place editing Fisher - Yates implementation. They are interchangeable (except that you would have to separate the print from the shuffle). For more information type perldoc -q rand on your shell.
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 placeforeach my $line (@lines) { print $line;}# fisher_yates_shuffle( \@array ) : generate a random permutation# of @array in placesub 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__