如何在Bash中生成一个范围内的随机数?
当前回答
生成随机的3位数字
这对于创建示例数据非常有用。示例:将所有测试数据放在名为“test-create-volume-123”的目录中,然后在测试完成后,删除整个目录。通过生成恰好三个数字,就不会有奇怪的排序问题。
printf '%02d\n' $((1 + RANDOM % 100))
这是按比例缩小的,例如到一个数字:
printf '%01d\n' $((1 + RANDOM % 10))
它可以放大,但只能放大到四位数。原因见上文:)
其他回答
请参阅$RANDOM:
$RANDOM是一个内部Bash函数 (不是常量)返回 范围内的伪随机整数 0 - 32767。它不应该被用来 生成加密密钥。
我已经采取了一些这些想法,并做出了一个函数,应该执行迅速,如果大量的随机数是必需的。
如果你需要很多随机数,调用od的代价是很高的。相反,我只调用它一次,并存储来自/dev/urandom的1024个随机数。当调用rand时,返回最后一个随机数并按比例缩放。然后从缓存中删除它。当缓存为空时,再读取1024个随机数。
例子:
rand 10; echo $RET
返回RET中0到9(含9)之间的随机数。
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
更新:这并不适用于所有n。如果使用小n,也会浪费随机比特。注意(在这种情况下)一个32位随机数有足够的熵容纳9个0到9之间的随机数(10*9=1,000,000,000 <= 2*32),我们可以从每个32个随机源值中提取多个随机数。
#!/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
我就此写了几篇文章。
https://linuxconfig.org/generating-random-numbers-in-bash-with-examples https://linuxconfig.org/random-entropy-in-bash https://www.cloudsavvyit.com/7572/how-to-generate-better-random-numbers-at-the-bash-command-line/
$ RANDOM=$(date +%s%N | cut -b10-19)
$ echo $(( $RANDOM % 113 + 13 ))
上述将给出一个介于13到125(113-1+13)之间的数字,具有合理的随机熵。
还可以使用shuf(可在coreutils中使用)。
shuf -i 1-100000 -n 1
使用随机的美元。它通常与简单的shell算法结合使用很有用。例如,要生成1到10(包括)之间的随机数:
$ echo $((1 + $RANDOM % 10))
3
实际的生成器在variables.c中,即函数brand()。旧版本是一个简单的线性生成器。bash 4.0版本使用了一个引用1985年论文的生成器,这可能意味着它是一个不错的伪随机数来源。我不会将它用于模拟(当然也不会用于加密),但它可能足以用于基本的脚本任务。
如果你在做一些需要大量随机数的事情,你可以使用/dev/random或/dev/urandom(如果它们可用的话):
$ dd if=/dev/urandom count=4 bs=1 | od -t d