# Generate Random Numbers on Bash or Shell Using Builtins \$random

As we all know, the shell builtin variable \$RANDOM is a pseudo random number generator.

Today, we will be looking at some creative ways to generate psuedo random numbers, trying to use shell builtins as much as possible.

## The Best Solution is shuf (not exactly builtin though)

```1234# Shuffle and return n'th line of range
shuf -n1 -i1-10000
9523

```

## Ways to generate various strings of numbers in BASH

```123# Generate a number between 0 - 32767
echo \$RANDOM
7469

```

## \$RANDOM Caveats

From the 2 above scenarios, we analyse the distribution of the digits and find out the frequency of each value in order to see how random they really are:

```12345678910111213141516# Count the frequency of numbers in a 10000 samples
# cut -c1 chops the first digit from our variable

for i in \$(seq 1 1000); do
RNUMS+=(\$(cut -c1 &lt;&lt;&lt; \$RANDOM))
done

### OR

while [[ \$COUNTER -le 1000 ]]; do
RNUMS+=(\$(cut -c1 &lt;&lt;&lt; \$RANDOM))
COUNTER=\$COUNTER+1
done

# show RNUMS array length, should be 1000
echo \${#RNUMS[@]}

```

Now, we want to test the frequency of each digit:

```1234567891011121314151617181920212223242526for n in \${RNUMS[@]}; do
case \$n in
1 ) ((ones++))
;;
2 ) ((twos++))
;;
3 ) ((three++))
;;
4 ) ((fours++))
;;
5 ) ((fives++))
;;
6 ) ((sixes++))
;;
7 ) ((sevens++))
;;
8 ) ((eights++))
;;
9 ) ((nines++))
;;
0 ) ((zeros++))
;;
esac
done

echo \$ones \$twos \$threes \$fours \$fives \$sixes \$sevens \$eights \$nines \$zeros

```

Strangely, the output expected should be ~100, ~100, ~100…

However, the output is totally different:

330 367 108 22 41 28 30 42 33

## Creative Ways To Generate Bad Random Numbers In Bash

### The second digit from \$RANDOM\$RANDOM

#### cut -c2 <<< \$RANDOM\$RANDOM

```1234567891011121314# cut the 2nd digit from RANDOMRANDOM
# \$RANDOM's minimum value is 1 therefore the second digit should always be there
# Do not use this value on its own though, as it clearly is not random
while [[ \$COUNTER -le 1000 ]]; do
RNUMS+=(\$(cut -c2 &lt;&lt;&lt; \$RANDOM\$RANDOM))
COUNTER=\$COUNTER+1
done
# frequency test
111 114 92 97 86 87 89 95 105 125

# again
120 100 108 93 100 97 78 83 97 125

# CLEARLY NOT RANDOM

```

### A digit from \$(date +%N)

#### cut -c9 <<< \$(date +%N)

```1234# Print the time in nanoseconds of the current moment
# Do not use this value on its own though, as it clearly is not random
date +%N
277936336

```
```1234567while [[ \$COUNTER -le 1000 ]]; do
RNUMS+=(\$(cut -c9 &lt;&lt;&lt; \$(date +%N)))
COUNTER=\$COUNTER+1
done
# frequency test
103 89 105 92 102 104 100 106 91 109
# DECENTLY RANDOM

```

### A digit from cksum <<< \$RANDOM\$RANDOM

#### cut -c2 <<< \$(cksum <<< \$RANDOM\$RANDOM)

```123# Checksum \$RANDOM\$RANDOM
echo \$(cksum &lt;&lt;&lt; \$RANDOM\$RANDOM)
277936336

```
```1234567891011while [[ \$COUNTER -le 1000 ]]; do
RNUMS+=(\$(cut -c2 &lt;&lt;&lt; \$(cksum &lt;&lt;&lt; \$RANDOM\$RANDOM)))
COUNTER=\$COUNTER+1
done
# frequency test
128 123 91 78 101 95 85 86 92 122
# again
124 111 110 79 82 91 100 103 84 117
# and again
126 118 104 92 101 85 88 87 86 114
# CLEARLY NOT RANDOM!

```

### A digit from cksum <<< \$((\$RANDOM*\$RANDOM))

#### cut -c2 <<< \$(cksum <<< \$((\$RANDOM*\$RANDOM)))

```123456789# Checksum \$RANDOM x \$RANDOM
while [[ \$COUNTER -le 1000 ]]; do
RNUMS+=(\$(cut -c2 &lt;&lt;&lt; \$(cksum &lt;&lt;&lt; \$((\$RANDOM*\$RANDOM)))))
COUNTER=\$COUNTER+1
done
# and analysis
112 127 107 103 88 84 106 85 81 108
126 106 97 99 85 99 88 83 105 113
# CLEARY NOT RANDOM!

```

### Shuf 1-10

#### shuf -n1 -i1-10

```123456789# Shuffle 1-10
while [[ \$COUNTER -le 1000 ]]; do
RNUMS+=(\$(shuf -n1 -i1-10))
COUNTER=\$COUNTER+1
done
# and analysis
95 107 76 93 113 88 116 109 110
101 95 116 100 107 109 83 91 103
# GREAT RANDOM NUMBER GENERATOR

```