1

How to generate 9 digit random number in shell?

I am trying something like this but it only gave numbers below 32768.

#!/bin/bash
mo=$((RANDOM%999999999))
echo "********Random"$mo

Please help

output should be ********Random453351111

Charles Duffy
  • 280,126
  • 43
  • 390
  • 441
Sobhit Sharma
  • 697
  • 14
  • 45

5 Answers5

3

In Linux with /dev/urandom:

$ rnd=$(tr -cd "[:digit:]" < /dev/urandom | head -c 9) && echo $rnd
463559879
James Brown
  • 36,089
  • 7
  • 43
  • 59
  • 3
    This works, but it's really unfortunate to be eating so much more data from `/dev/urandom` than you really need (since anything that isn't a digit just gets thrown out). A better way to use `/dev/urandom` would be to read only a single 64-bit integer _as 64 bits of data_, so the total amount of entropy consumed is constrained to 8 bytes -- though that's easier to write in Python or C than bash. – Charles Duffy Mar 25 '21 at 16:06
2

I think this should make it

shuf -i 99999999-999999999 -n 1

Ivan
  • 1,352
  • 2
  • 13
  • 31
1

Because of RANDOM's limited range, it can only be used to retrieve four base-10 digits at a time. Thus, to retrieve 9 digits, you need to call it three times.

If we don't care much about performance (are willing to pay process substitution costs), this may look like:

#!/usr/bin/env bash
get4() {
  local newVal=32768
  while (( newVal > 29999 )); do # avoid bias because of remainder
    newVal=$RANDOM
  done
  printf '%04d' "$((newVal % 10000))"
}

result="$(get4)$(get4)$(get4)"
result=$(( result % 1000000000 ))
printf '%09d\n' "$result"

If we do care about performance, it may instead look like:

#!/usr/bin/env bash
get4() {
  local newVal=32768 outVar=$1
  while (( newVal > 29999 )); do # avoid bias because of remainder
    newVal=$RANDOM
  done
  printf -v "$outVar" '%04d' "$((newVal % 10000))"
}

get4 out1; get4 out2; get4 out3
result="${out1}${out2}${out3}"
result=$(( result % 1000000000 ))
printf '%09d\n' "$result"
Charles Duffy
  • 280,126
  • 43
  • 390
  • 441
  • Let me try this too. – Sobhit Sharma Mar 25 '21 at 16:01
  • _nod_ -- the 1-digit-at-a-time way works, but it consumes more entropy than it needs; 4-at-a-time is faster (when you use the version that isn't slowed down by use of `$(...)`); and also this provides a more random number on account of rerolling things that don't divide evenly into 10,000. – Charles Duffy Mar 25 '21 at 16:02
1

As a work around, we could just simply ask for 1 random integer, for n times:

rand=''
for i in {1..9}; do
    rand="${rand}$(( $RANDOM % 10 ))"
done

echo $rand

Try it online!


Note [1]: Since RANDOM's upper limit has a final digit of 7, there's a slightly lesser change for the 'generated' number to contain 8 or 9's.

0stone0
  • 34,288
  • 4
  • 39
  • 64
  • 4
    BTW, this is ever-so-slightly biased. Because `RANDOM` goes up to a number with a final digit of 7, that means 8 and 9 are slightly less likely than the digits below them. – Charles Duffy Mar 25 '21 at 16:03
0

Use perl, as follows :

perl -e print\ rand | cut -c 3-11 

Or

perl -MPOSIX -e 'print floor rand 10**9'
MUY Belgium
  • 2,330
  • 4
  • 30
  • 46