22

How can print a value, either 1, 2 or 3 (at random). My best guess failed:

#!/bin/bash

1 = "2 million"
2 = "1 million"
3 = "3 million"

print randomint(1,2,3)
3
  • 2
    The minimal question is: pick one integer out of {1, 2, 3} Commented Apr 28, 2015 at 8:20
  • stackoverflow.com/questions/2556190/… + arrays solves this. Commented Apr 28, 2015 at 8:30
  • 1
    what are those 1 = "2 million" lines supposed to mean? They aren't valid bash constructs. Commented Jan 23, 2017 at 22:16

5 Answers 5

31

To generate random numbers with bash use the $RANDOM internal Bash function:

arr[0]="2 million"
arr[1]="1 million"
arr[2]="3 million"

rand=$[ $RANDOM % 3 ]
echo ${arr[$rand]}

From bash manual for RANDOM:

Each time this parameter is referenced, a random integer between 0 and 32767 is generated. The sequence of random numbers may be initialized by assigning a value to RANDOM. If RANDOM is unset,it loses its special properties, even if it is subsequently reset.

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

3 Comments

$[ ] is a compatibility construct to support 1970s-era Bourne syntax; that construct is not found in more recent standards, and thus not guaranteed to be supported by more modern shells other than bash (which has historically included it). Since 1991, when POSIX sh was published, the standardized math construct has been $(( )), so this should be rand=$(( RANDOM % 3 )).
I would also suggest quoting -- as in, echo "${arr[$rand]}"; that way we won't have unexpected behavior with different values in IFS, or with array values that expand as globs. (For instance, if IFS=0123456789, then echo ${arr[$rand} without the quotes wouldn't print any number at all).
How about rand=$[ $RANDOM % ${#arr[@]} ] to avoid hardcoding 3?
9

Coreutils shuf

Present in Coreutils, this function works well if the strings don't contain newlines.

E.g. to pick a letter at random from a, b and c:

printf 'a\nb\nc\n' | shuf -n1

POSIX eval array emulation + RANDOM

Modifying Marty's eval technique to emulate arrays (which are non-POSIX):

a1=a
a2=b
a3=c
eval echo \$$(expr $RANDOM % 3 + 1)

This still leaves the RANDOM non-POSIX.

awk's rand() is a POSIX way to get around that.

2 Comments

what is "shuf"; linux? i don't see it on mac osx, and arrays are so ugly. see following answer
@MartyMcGowan GNU non-POSIX as linked. Agree that arrays are ugly, but first option with shuf does not use the arrays. Agree that greater portability would be cool. I didn't know set could set the arguments as you proposed, that's interesting.
5

64 chars alpha numeric string

randomString32() {
    index=0
    str=""

    for i in {a..z}; do arr[index]=$i; index=`expr ${index} + 1`; done
    for i in {A..Z}; do arr[index]=$i; index=`expr ${index} + 1`; done
    for i in {0..9}; do arr[index]=$i; index=`expr ${index} + 1`; done
    for i in {1..64}; do str="$str${arr[$RANDOM%$index]}"; done

    echo $str
}

1 Comment

I believe this does not answer the question: OP wants to pick one out of 3 strings, not generate a completely random one. And /dev/random is better for that.
1
~.$ set -- "First Expression" Second "and Last"
~.$ eval echo \$$(expr $RANDOM % 3 + 1)
and Last
~.$ 

Comments

1

Want to corroborate using shuf from coreutils using the nice -n1 -e approach.

Example usage, for a random pick among the values a, b, c:

CHOICE=$(shuf -n1 -e a b c)
echo "choice: $CHOICE"

I looked at the balance for two samples sizes (1000, and 10000):

$ for lol in $(seq 1000); do shuf -n1 -e a b c; done > shufdata
$ less shufdata | sort | uniq -c
    350 a
    316 b
    334 c
$ for lol in $(seq 10000); do shuf -n1 -e a b c; done > shufdata
$ less shufdata | sort | uniq -c
   3315 a
   3377 b
   3308 c

Ref: https://www.gnu.org/software/coreutils/manual/html_node/shuf-invocation.html

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.