0

With the shell script, I wish to generate five files, and I wish to put different random number range from 50000~150000 in each file. I tried something like following,

for i in 01 02 03 04 05; do
A=$((50000+100000))
B=$(($B%$A))
cat > ${i}.dat << EOF
AArandom=$A
EOF
done

But this does not work.... How can I make random numbers and print out for each file?

4
  • @Steve not a duplicate, because of the range requirement: $RANDOM produces numbers in the range 0 - 32767, but here a bigger range is required. Commented Jul 16, 2017 at 7:25
  • If you want to do something in bash, man bash is often a good way to start. The man page is long; search for keywords, like random... Commented Jul 16, 2017 at 7:25
  • I think the question should be reworded to explicitly note the range >32767 requirement. Commented Jul 16, 2017 at 7:28
  • In the above loop $B wasn't used to output anything. Commented Jul 17, 2017 at 1:39

2 Answers 2

4

Each time you read the value of the variable $RANDOM, it gives you a random number between 0 and 2^15 - 1, that is 0 and 32767. So that doesn't give you enough range. You could use two $RANDOM as two digits of base-15, and then take appropriate modulo and apply appropriate range normalization.

Here's the logic wrapped in a function:

randrange() {
    min=$1
    max=$2

    ((range = max - min))

    ((maxrand = 2**30))
    ((limit = maxrand - maxrand % range))

    while true; do
        ((r = RANDOM * 2**15 + RANDOM))
        ((r < limit)) && break
    done

    ((num = min + r % range))
    echo $num
}

And then you can generate the files in a loop like this:

for i in 01 02 03 04 05; do
  echo "AArandom=$(randrange 50000 150000)" > $i.dat
done

Note that there is a caveat in the implementation of randrange: there is a loop to re-roll in case the value would be biased, but theoretically this may prevent the function from terminating. In practice, that's extremely unlikely, but deserves a mention.

Sign up to request clarification or add additional context in comments.

3 Comments

Nice solution to extend the range. The result is biased though, so you'll want to use a different construct if you want a completely uniform distribution. To see why, consider a range of 1 less than the highest number which can be handled by randrange, (2^15-1) * 2^15 + (2^15-1). Using that range there are exactly one combination of two RANDOM numbers resulting in each output number greater than 1, and two combinations resulting in 1 (one random number equal 0 and the other 1, or both numbers equal 2^15-1), making a result of 1 twice as likely as any other number.
@l0b0 good call, thanks. I think I corrected it, with the "minor" caveat that the program might never terminate if you have really bad luck =)
RANDOM is a bash extension, it is not a general solution to getting a random number in a shell script.
2

shuf is probably what you want:

$ shuf -i 50000-150000 -n 1
148495

2 Comments

Nice and easy and as uniform as it gets, no sweat ;-)
Thank you but one more question. How can I use shuf command inside the bash script with cat command?

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.