so.very.tired so.very.tired - 3 months ago 9
Bash Question

Shell's `RANDOM` is not determined by seed when used with `awk`

Consider the following shell script, and the output that follows...

#!/bin/bash

RANDOM=5

for i in {0..9..1}
do
rand_val=$(awk -v rand_awk=$RANDOM 'BEGIN{print rand_awk;}')
echo "generated $RANDOM"
echo "generated in awk: $rand_val"
done


First run:

generated 18499
generated in awk: 9147
generated 9909
generated in awk: 20212
generated 24640
generated in awk: 24874
generated 15572
generated in awk: 2499
generated 5516
generated in awk: 10235
generated 17897
generated in awk: 8039
generated 19000
generated in awk: 26744
generated 12793
generated in awk: 2500
generated 27730
generated in awk: 20895
generated 5509
generated in awk: 887


Second run:

generated 18499
generated in awk: 16728
generated 9909
generated in awk: 31548
generated 24640
generated in awk: 11705
generated 15572
generated in awk: 10184
generated 5516
generated in awk: 6024
generated 17897
generated in awk: 838
generated 19000
generated in awk: 20789
generated 12793
generated in awk: 3646
generated 27730
generated in awk: 21647
generated 5509
generated in awk: 18333


Third run:

generated 18499
generated in awk: 6725
generated 9909
generated in awk: 9301
generated 24640
generated in awk: 24364
generated 15572
generated in awk: 19016
generated 5516
generated in awk: 21737
generated 17897
generated in awk: 9027
generated 19000
generated in awk: 17942
generated 12793
generated in awk: 19478
generated 27730
generated in awk: 9555
generated 5509
generated in awk: 31563


It looks like inside
awk
statement, the numbers generated by
RANDOM
are not affected by the seed (5).
I want
rand_val
to also be effected by the seed that
RANDOM
gets, mainly because I want to use
awk
's
rand()
function in a predictable way:

#!/bin/bash

RANDOM=5
RANGE=3

for i in {0..9..1}
do
rand_val=$(awk -v rand_awk=$RANDOM -v range=$RANGE 'BEGIN{srand(rand_awk); print rand()*range;}')
echo "generated in awk: $rand_val"
done

Answer

I suspect it's the fact that $(...) creates a subshell and RANDOM is a special variable. A minor change gets your first script to respond consistently:

#!/bin/bash

RANDOM=5

for i in {0..9..1}
do
        R=$RANDOM
        rand_val=$(RANDOM=$R awk -v rand_awk=$R 'BEGIN{print rand_awk;}')
        echo "generated $RANDOM"
        echo "generated in awk: $rand_val"
done

I simply reassigned $RANDOM to another variable, and passed that in instead.

Comments