232

How would I generate an inclusive random number between 1 to 10 in Bash Shell Script?

Would it be $(RANDOM 1+10)?

2
  • 2
    tldp.org/LDP/abs/html/randomvar.html Commented Jan 24, 2012 at 14:53
  • this works for what I need export CUDA_VISIBLE_DEVICES=$((( RANDOM % 8 ))) Commented Mar 11, 2021 at 20:47

6 Answers 6

389
$(( ( RANDOM % 10 )  + 1 ))

EDIT. Changed brackets into parenthesis according to the comment. http://web.archive.org/web/20150206070451/http://islandlinux.org/howto/generate-random-numbers-bash-scripting

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

7 Comments

I get a syntax error: syntax error near unexpected token `+' on Linux
The % 10 reduces the result to a set of ranges from 0-9. However, the very top set only has a range of 0-7. Thus, there are two fewer draws for 8 & 9 than 0-7. The + 1 translates this to a bias against 9 & 10. This would be a major flaw in security contexts - an RNG must not display bias, and at scale this is noticeable. Further explanation: Anatomy of a pseudorandom number generator - visualising Cryptocat's buggy PRNG.
@BradKoch How do we know that Bash's RNG makes that error?
@ads20000 The docs say so, man bash, "Each time this parameter is referenced, a random integer between 0 and 32767 is generated." Note that this is not a bash error, it's an error of the implementer. Assuming bash implemented $RANDOM correctly, there should be a fair draw from numbers 0 to 32767, but because you can't divide that evenly into groups of 10, there is a very small bias against 9 and 10 in this implementation. Most people shouldn't need to worry about this, because you shouldn't be using $RANDOM for security purposes anyway.
By far the simplest solution
|
122

Simplest solution would be to use tool which allows you to directly specify ranges, like shuf

shuf -i1-10 -n1

If you want to use $RANDOM, it would be more precise to throw out the last 8 numbers in 0...32767, and just treat it as 0...32759, since taking 0...32767 mod 10 you get the following distribution

0-8 each: 3277 
8-9 each: 3276

So, slightly slower but more precise would be

while :; do ran=$RANDOM; ((ran < 32760)) && echo $(((ran%10)+1)) && break; done 

1 Comment

I found this question looking for /bin/sh even though the question requests bash. The shuf technique appears to work in both bash and sh.
45

To generate random numbers with bash use the $RANDOM internal Bash function. Note that $RANDOM should not be used to generate an encryption key. $RANDOM is generated by using your current process ID (PID) and the current time/date as defined by the number of seconds elapsed since 1970.

 echo $RANDOM % 10 + 1 | bc

4 Comments

I found $RANDOM cannot generate big number, so I use date +%s to get a big number. echo $(date +%s) % 4 | bc
What does the "| bc" part do?
@ebi echo just prints the string (variable substitution happens before the command is processed, so $RANDOM is already replaced with an integer by that point), bc is what actually evaluates it when the | redirects the stdout from the echo into the stdin of the bc
Works well on Mac OS X. +1
34

You can also use /dev/urandom:

grep -m1 -ao '[0-9]' /dev/urandom | sed s/0/10/ | head -n1

3 Comments

Useful when you don't have $RANDOM available, i.e. busybox
clever trick sed s/0/10/ !
Great trick especially for Github Actions!
25

To generate in the range: {0,..,9}

r=$(( $RANDOM % 10 )); echo $r

To generate in the range: {40,..,49}

r=$(( $RANDOM % 10 + 40 )); echo $r

Comments

-6

Here is example of pseudo-random generator when neither $RANDOM nor /dev/urandom is available

echo $(date +%S) | grep -o .$ | sed s/0/10/

2 Comments

It just prints an increasing sequence of numbers every time I run it: "1... 2... 3.... 4..." basically, the least-significant digit of the current second.
A date is not random at all. It is completely predictable and follows an obvious pattern.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.