14

In a program, I need to set a variable to a random value of either 0 or 1.

I can't figure out how to do it and Google has failed me.

30

One easy method is to use $RANDOM to retrieve a pseudorandom 16 bit integer number in the range [0; 32767]. You can simply convert that to [0; 1] by calculating modulo 2 of the random number:

echo $(( $RANDOM % 2 ))

More information about Bash's $RANDOM: http://www.tldp.org/LDP/abs/html/randomvar.html

With that simple construct you can easily build powerful scripts using randomness, like in this comic...

Commit Strip - Russian Roulette

  • 4
    The pedant in me feels the need to point out that the chosen production server destroying command won't do anything without --no-preserve-root - so maybe not the game of Russian Roulette they were hoping for... – Boris the Spider Jan 19 '17 at 14:11
  • 2
    @BoristheSpider they are using the antiquated $[] syntax - who knows whether their rm had that --no-preserve-root feature? – muru Jan 19 '17 at 16:17
  • 10
    @BoristheSpider My interpretation of the comic is that, when they see the message rm: it is dangerous to operate recursively on '/' rm: use --no-preserve-root to override this failsafe, they hang their head low and, knowing they have lost the game, proceed to erase their disk with dd, out of honor. – Eliah Kagan Jan 19 '17 at 16:28
  • @EliahKagan ah, seppuku. Understood. – Boris the Spider Jan 19 '17 at 16:29
  • @BoristheSpider: The --no-preserve-root got only implemented "lately". Have no information on when it was implemented, but IIRC it is only a few years old. And that's a tiny amount when it comes to Linux. Here is a ticket about this: bugs.launchpad.net/ubuntu/+source/coreutils/+bug/174283 – Shiki Jan 20 '17 at 11:09
13

You could use shuf

DESCRIPTION
     Write a random permutation of the input lines to standard output.

     -i, --input-range=LO-HI
            treat each number LO through HI as an input line
     -n, --head-count=COUNT
            output at most COUNT lines

Example:

$ foo=$(shuf -i0-1 -n1)
$ echo $foo
1
$ foo=$(shuf -i0-1 -n1)
$ echo $foo
0
$ foo=$(shuf -i0-1 -n1)
$ echo $foo
0
$ foo=$(shuf -i0-1 -n1)
$ echo $foo
1
5

How about:

#!/bin/bash
r=$(($RANDOM % 2))
echo $r

Or even:

r=$(($(od -An -N1 -i /dev/random) % 2))

Or perhaps:

r=$(seq 0 1 | sort -R  | head -n 1)

Or more hackily:

r=$(($(head -128 /dev/urandom | cksum | cut -c1-10) % 2))

And also:

r=$(apg -a 1 -M n -n 1 -m 8 -E 23456789  | cut -c1)

As well as:

r=$((0x$(cut -c1-1 /proc/sys/kernel/random/uuid) % 2))
1

This script has no benefits over existing answers. Just for entertainment purposes...

Get one byte from /dev/urandom (although in general sending arbitrary binary characters to console is not recommended™ because it might give unexpected/confusing results):

head -c 1 /dev/urandom

And turn in into decimal number:

head -c 1 /dev/urandom | od -An -t u1

And get the remainder of its division by 2:

echo $((`head -c 1 /dev/urandom | od -An -t u1` % 2))

Your Answer

By clicking "Post Your Answer", you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.