如何在Bash中生成随机数字?
如何在Bash范围内生成一个随机数字?
使用$RANDOM
。 与简单的shellalgorithm结合使用通常很有用。 例如,要生成一个1到10之间的随机数:
$ echo $((1 + RANDOM % 10)) 3
实际的生成器在variables.c
,函数brand()
。 旧版本是一个简单的线性发生器。 bash
版本4.0使用一个引用 1985年论文的发生器 ,这大概意味着它是伪随机数的一个体面的来源。 我不会将它用于模拟(当然不是用于encryption),但对于基本的脚本任务来说可能是足够的。
如果你正在做的事情需要严重的随机数字,你可以使用/dev/random
或/dev/urandom
如果它们是可用的):
$ dd if=/dev/urandom count=4 bs=1 | od -td
请参阅$RANDOM
:
$RANDOM
是一个内部的Bash函数(不是一个常量),它返回一个范围为0 – 32767的伪随机整数。它不应该被用来产生一个encryption密钥。
尝试从你的shell:
$ od -A n -td -N 1 /dev/urandom
在这里, -td
指定输出格式应该是十进制的; -N 1
表示从/dev/urandom
读取一个字节。
有$ RANDOM。 我不知道它是如何工作的。 但它的作品。 为了testing,你可以这样做:
echo $RANDOM
你也可以从awk得到随机数
awk 'BEGIN { # seed srand() for (i=1;i<=1000;i++){ print int(1 + rand() * 100) } }'
介于0和9之间的随机数。
echo $((RANDOM%10))
你也可以使用shuf (在coreutils中可用)。
shuf -i 1-100000 -n 1
如果您使用的是Linux系统,则可以从/ dev / random或 / dev / urandom中获取一个随机数。 如果没有足够的随机数可用,小心/ dev / random会阻塞。 如果你需要速度超过随机使用/ dev / urandom。
这些“文件”将被操作系统生成的随机数填充。 如果你得到真或伪随机数,它取决于你系统上/ dev / random的实现。 真正的随机数是通过从设备驱动程序(如鼠标,硬盘驱动器,networking)收集到的帮助形成的。
你可以用dd从文件中得到随机数字
我已经采取了一些这些想法,并做了一个function,应该快速执行,如果大量的随机数是必需的。
如果你需要大量的随机数,调用od
是昂贵的。 相反,我把它调用一次,从/ dev / urandom存储1024个随机数。 当rand
被调用时,最后一个随机数被返回并缩放。 然后从caching中删除。 当caching为空时,读取另外的1024个随机数。
例:
rand 10; echo $RET
返回0到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 -ic; 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和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 -ic 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
从/ dev / random或/ dev / urandom字符特殊文件读取是要走的路。
这些设备在读取时返回真正的随机数,旨在帮助应用程序软件select用于encryption的安全密钥。 这样的随机数是从各种随机事件贡献的熵池中提取的。 {LDD3,Jonathan Corbet,Alessandro Rubini和Greg Kroah-Hartman]
这两个文件特别是与内核随机化的接口
void get_random_bytes_arch(void* buf, int nbytes)
如果这样的function是通过硬件实现的(通常是),或者从熵池(包括事件之间的定时,如鼠标和键盘中断以及其他在SA_SAMPLE_RANDOM中注册的中断)中抽取,则从硬件抽取真正的随机字节。
dd if=/dev/urandom count=4 bs=1 | od -td
这工作,但写入dd
不需要的输出到标准输出。 下面的命令只给出我需要的整数。 我甚至可以根据需要通过调整给算术扩展的位掩码来获得指定数量的随机位:
me@mymachine:~/$ x=$(head -c 1 /dev/urandom > tmp && hexdump -d tmp | head -n 1 | cut -c13-15) && echo $(( 10#$x & 127 ))
我喜欢这个技巧:
echo ${RANDOM:0:1} # random number between 1 and 9 echo ${RANDOM:0:2} # random number between 1 and 99
…
生成0到n范围内的随机数(带符号的16位整数)。 在$ RANDvariables中设置结果。 例如:
#!/bin/bash random() { local range=${1:-1} RAND=`od -t uI -N 4 /dev/urandom | awk '{print $2}'` let "RAND=$RAND%($range+1)" } n=10 while [ $(( n -=1 )) -ge "0" ]; do random 500 echo "$RAND" done
关于什么:
perl -e 'print int rand 10, "\n"; '