Rob Hudson wrote:
> > On 20010925.1701, Bob Miller said ...
> >
> > Rob Hudson wrote:
> >
> > > I want to pick a random word from dict/words file, basically pick a
> > > random line in a file.
> >
> > $ perl -ne '$l = $_ if ! int rand $n++; END { print $l }' /usr/dict/words
>
> I found another version using perl and avoids the 'slurp the whole
> file into memory' approach...
>
> cat /usr/share/dict/words | \
> perl -e 'srand; rand($.) < 1 && ($line = $_) while <>; print $line;'
>
>
> I can't see what yours is doing, though. Care to explain?
They're basically the same. I forgot about $. (aka $NR) so I used
a variable, $n, to count lines. I used the "-n" flag to create the
loop implicitly. According to the perlrun man page, perl -ne xxx
is equivalent to perl -e 'LINE: while (<>) { xxx }'. So my code,
expanded, would be:
LINE:
while (<>) {
$l = $_ if ! int rand $n++;
END { print $l }
}
$. (yours) is the current input line number, and $n (mine) is the
current line number minus one. So mine has a bug -- the last line
in the file will never be selected. I should have written ++$n
instead of $n++.
Of course, "! int rand <line-number>" is the same as
"rand(<line-number>) < 1". The former truncates the random number
toward zero, and compares to zero, so it's true whenever the random
number is less than one.
And the overall command structure. I wrote:
$ perl args file
and you wrote:
$ cat file | perl args
The call to srand is not needed. See the "rand" section of
perlfunc(3).
So we can combine the best features of both versions and come up
with this.
$ perl -ne '$line = $_ if rand($.) < 1; END { print $line; }' /usr/dict/words
Of course, I'm avoiding the question of how this algorithm gives each
of the available words with equal probability, but trust me, it
does. (-:
--
Bob Miller K<bob>
kbobsoft software consulting
http://kbobsoft.com [EMAIL PROTECTED]