How to generate a random number within a range in Bash?
问题:
回答1:
Use $RANDOM
. It's often useful in combination with simple shell arithmetic. For instance, to generate a random number between 1 and 10:
$ echo $((1 + RANDOM % 10))
3
The actual generator is in variables.c
, the function brand()
. Older versions were a simple linear generator. Version 4.0 of bash
uses a generator with a citation to a 1985 paper, which presumably means it's a decent source of pseudorandom numbers. I wouldn't use it for a simulation (and certainly not for crypto), but it's probably adequate for basic scripting tasks.
If you're doing something that requires serious random numbers you can use /dev/random
or /dev/urandom
if they're available:
$ dd if=/dev/urandom count=4 bs=1 | od -t d
回答2:
Please see $RANDOM
:
$RANDOM
is an internal Bash function (not a constant) that returns a pseudorandom integer in the range 0 - 32767. It should not be used to generate an encryption key.
回答3:
Try this from your shell:
$ od -A n -t d -N 1 /dev/urandom
Here, -t d
specifies that the output format should be signed decimal; -N 1
says to read one byte from /dev/urandom
.
回答4:
You can also use shuf (available in coreutils).
shuf -i 1-100000 -n 1
回答5:
you can also get random number from awk
awk 'BEGIN {
# seed
srand()
for (i=1;i<=1000;i++){
print int(1 + rand() * 100)
}
}'
回答6:
There is $RANDOM. I don't know exactly how it works. But it works. For testing, you can do :
echo $RANDOM
回答7:
Random number between 0 and 9 inclusive.
echo $((RANDOM%10))
回答8:
I like this trick:
echo ${RANDOM:0:1} # random number between 1 and 9
echo ${RANDOM:0:2} # random number between 1 and 99
...
回答9:
If you are using a linux system you can get a random number out of /dev/random or /dev/urandom. Be carefull /dev/random will block if there are not enough random numbers available. If you need speed over randomness use /dev/urandom.
These "files" will be filled with random numbers generated by the operating system. It depends on the implementation of /dev/random on your system if you get true or pseudo random numbers. True random numbers are generated with help form noise gathered from device drivers like mouse, hard drive, network.
You can get random numbers from the file with dd
回答10:
I have taken a few of these ideas and made a function that should perform quickly if lots of random numbers are required.
calling od
is expensive if you need lots of random numbers. Instead I call it once and store 1024 random numbers from /dev/urandom. When rand
is called, the last random number is returned and scaled. It is then removed from cache. When cache is empty, another 1024 random numbers is read.
Example:
rand 10; echo $RET
Returns a random number in RET between 0 and 9 inclusive.
declare -ia RANDCACHE
declare -i RET RAWRAND=$(( (1<<32)-1 ))
function rand(){ # pick a random number from 0 to N-1. Max N is 2^32
local -i N=$1
[[ ${#RANDCACHE[*]} -eq 0 ]] && { RANDCACHE=( $(od -An -tu4 -N1024 /dev/urandom) ); } # refill cache
RET=$(( (RANDCACHE[-1]*N+1)/RAWRAND )) # pull last random number and scale
unset RANDCACHE[${#RANDCACHE[*]}-1] # pop read random number
};
# test by generating a lot of random numbers, then effectively place them in bins and count how many are in each bin.
declare -i c; declare -ia BIN
for (( c=0; c<100000; c++ )); do
rand 10
BIN[RET]+=1 # add to bin to check distribution
done
for (( c=0; c<10; c++ )); do
printf "%d %d\n" $c ${BIN[c]}
done
UPDATE: That does not work so well for all N. It also wastes random bits if used with small N. Noting that (in this case) a 32 bit random number has enough entropy for 9 random numbers between 0 and 9 (10*9=1,000,000,000 <= 2*32) we can extract multiple random numbers from each 32 random source value.
#!/bin/bash
declare -ia RCACHE
declare -i RET # return value
declare -i ENT=2 # keep track of unused entropy as 2^(entropy)
declare -i RND=RANDOM%ENT # a store for unused entropy - start with 1 bit
declare -i BYTES=4 # size of unsigned random bytes returned by od
declare -i BITS=8*BYTES # size of random data returned by od in bits
declare -i CACHE=16 # number of random numbers to cache
declare -i MAX=2**BITS # quantum of entropy per cached random number
declare -i c
function rand(){ # pick a random number from 0 to 2^BITS-1
[[ ${#RCACHE[*]} -eq 0 ]] && { RCACHE=( $(od -An -tu$BYTES -N$CACHE /dev/urandom) ); } # refill cache - could use /dev/random if CACHE is small
RET=${RCACHE[-1]} # pull last random number and scale
unset RCACHE[${#RCACHE[*]}-1] # pop read random number
};
function randBetween(){
local -i N=$1
[[ ENT -lt N ]] && { # not enough entropy to supply ln(N)/ln(2) bits
rand; RND=RET # get more random bits
ENT=MAX # reset entropy
}
RET=RND%N # random number to return
RND=RND/N # remaining randomness
ENT=ENT/N # remaining entropy
};
declare -ia BIN
for (( c=0; c<100000; c++ )); do
randBetween 10
BIN[RET]+=1
done
for c in ${BIN[*]}; do
echo $c
done
回答11:
Reading from /dev/random or /dev/urandom character special files is the way to go.
These devices return truly random numbers when read and are designed to help application software choose secure keys for encryption. Such random numbers are extracted from an entropy pool that is contributed by various random events. {LDD3, Jonathan Corbet, Alessandro Rubini, and Greg Kroah-Hartman]
These two files are interface to kernel randomization, in particular
void get_random_bytes_arch(void* buf, int nbytes)
which draws truly random bytes from hardware if such function is by hardware implemented (usually is), or it draws from entropy pool (comprised of timings between events like mouse and keyboard interrupts and other interrupts that are registered with SA_SAMPLE_RANDOM).
dd if=/dev/urandom count=4 bs=1 | od -t d
This works, but writes unneeded output from dd
to stdout. The command below gives just the integer I need. I can even get specified number of random bits as I need by adjustment of the bitmask given to arithmetic expansion:
me@mymachine:~/$ x=$(head -c 1 /dev/urandom > tmp && hexdump
-d tmp | head -n 1 | cut -c13-15) && echo $(( 10#$x & 127 ))