[BASHISM] How to generate random number without $RANDOM ?

There is a common bashism, that is to use $RANDOM. Typically you’ll have to remove bashism while rewriting your scripts for dash or sh.

There is a lot of solutions to generate random numbers in many different ways, but I’m not here to pollute the internet demonstrating 42 differents ways to do this, i’ll only show you the one I think is the best, and let you comment it if you can do better :-)

My solution is to replace $RANDOM by :

$(($(dd if=/dev/urandom count=1 2> /dev/null | cksum | cut -d' ' -f1) % 32768))

Pros :

  • Not so long
  • Yield a different number each call (not all replacement for $RANDOM do)
  • Excatly like in bash, it yield a number between 0 and 32767

Cons :

  • Longer than $RANDOM :p
  • /dev/urandom is not present on every systems …

You should simplify it if the [0, 32767] rule has no importance for you, typically if you want a number between 0 and 10, don’t do … % 32768)) % 11)) …

This entry was posted in Shell Script. Bookmark the permalink.

3 Responses to [BASHISM] How to generate random number without $RANDOM ?

  1. Vasudev Ram says:

    I would do this instead (off the top of my head, not evaluated thoroughly):

    – Write a C program to generate random numbers in the same way that $RANDOM does. Then call it in place of $RANDOM, like so (assume it’s called rnd).

    In code using $RANDOM => Use `rnd` or $(rnd)
    (Arrange for rnd.c to send its random number output to standard output.)

    – shorter than your solution using dd and /dev/urandom (Not much of a pro, except if using it a lot, and also, you could make your own solution shorter to type by packaging part of it in a shell script with a short name and then call that script with the rest of the original command line – or you might even be able to use a shell alias in cases where the dd / urandom code comes at the start of the command line).

    – Since it is a C program, not a bash built-in like $RANDOM, it would load slower, which could be an issue in loops that run many times, depending on whether the Linux version keeps the executable in memory or not between invocations.
    – C compiler may not be available on all Linux machines where you want to use it, whereas bash should be. Could carry the executable on a USB stick and run it from the stick, or copy it to hard disk, but would need to do it on each new machine you use (if you use a lot of machines).

    There can be other pros and cons, not evaluated in detail …

    – Vasudev

  2. browseman says:

    This method is far more elegant:

    grep -m1 -ao ‘[0-1][0-2][0-9]’ /dev/urandom

    It was taken from here:

    • I prefer my version, imagine if you have to wait 2 years to get three consecutive numbers from urandom ? Demo time (Mine : 0m0.002s, Yours: 0m0.379s).

      $ time grep -m1 -ao ‘[0-1][0-2][0-9]’ /dev/urandom

      real 0m0.379s
      user 0m0.228s
      sys 0m0.148s

      $ time echo $(($(dd if=/dev/urandom count=1 2> /dev/null | cksum | cut -d’ ‘ -f1) % 32768))

      real 0m0.002s
      user 0m0.000s
      sys 0m0.000s

Leave a Reply

Your email address will not be published. Required fields are marked *

You may use these HTML tags and attributes: <a href="" title=""> <abbr title=""> <acronym title=""> <b> <blockquote cite=""> <cite> <code> <del datetime=""> <em> <i> <q cite=""> <s> <strike> <strong>