Answers:
使用$RANDOM
。与简单的Shell算术结合使用时通常很有用。例如,要生成1到10(含)之间的随机数:
$ echo $((1 + RANDOM % 10))
3
实际的发电机在variables.c
,功能brand()
。旧版本是一个简单的线性发电机。版本4.0 bash
使用引用了1985年论文的生成器,这大概意味着它是伪随机数的一个不错的来源。我不会将其用于模拟(当然也不会用于加密),但它可能足以满足基本脚本任务的需要。
如果您要执行的操作需要严重的随机数,则可以使用/dev/random
或/dev/urandom
可用:
$ dd if=/dev/urandom count=4 bs=1 | od -t d
$RANDOM % 10
,即使$RANDOM
是可靠的随机数据源,8和9的概率(尽管在边际上)也比0-7小得多。
您也可以使用shuf(在coreutils中可用)。
shuf -i 1-100000 -n 1
shuf -i 1-10 -n 1: syntax error in expression (error token is "1-10 -n 1")
$var
而不是范围末尾,例如:var=100 && shuf -i 1-${var} -n 1
-n
。例如,生成1至100之间的5个随机数:shuf -i 1-100 -n 5
shuf -i 1-10 -n 10
,则将得到从1到10的所有数字,精确到一个。如果您指定,-n 15
您仍然只会准确地获得那10个数字。这实际上只是改组,不会生成随机数。
你也可以从awk获得随机数
awk 'BEGIN {
# seed
srand()
for (i=1;i<=1000;i++){
print int(1 + rand() * 100)
}
}'
srand()
,的种子是当前的CPU时间。如果需要指定特定的种子,以便可以复制RNG,请使用srand(x)
where x
是种子。同样,引自GNU awk的数字功能手册,“不同的awk实现内部使用了不同的随机数生成器。” 结果是,如果您对生成统计信息分布感兴趣,则应该期望从一个运行时到另一个运行在不同平台(所有运行awk
或gawk
)上的轻微变化。
有$ RANDOM。我不知道它是如何工作的。但这有效。为了进行测试,您可以执行以下操作:
echo $RANDOM
我喜欢这个技巧:
echo ${RANDOM:0:1} # random number between 1 and 9
echo ${RANDOM:0:2} # random number between 1 and 99
...
${RANDOM:0:1}
给您1或2的几率达67.8%,给您一个${RANDOM:0:2}
数字(应为1%)的几率只有0.03%,给您0的几率都为0.003% 。在某些情况下,这仍然很好(例如,输入不一致)。
介于0和9之间(含0和9)的随机数。
echo $((RANDOM%10))
$RANDOM
只能从0到32767。它应该说“随机数通常在1到3之间,并且有一些边锋”;)
如果您使用的是Linux系统,则可以从/ dev / random或 / dev / urandom中获得随机数。请注意,如果没有足够的随机数,/ dev / random将被阻止。如果您需要速度超过随机性,请使用/ dev / urandom。
这些“文件”将填充由操作系统生成的随机数。如果获得真或伪随机数,则取决于系统上/ dev / random的实现。真正的随机数是借助从鼠标,硬盘驱动器,网络等设备驱动程序收集到的噪声形式生成的。
您可以使用dd从文件中获取随机数
我采纳了其中的一些想法,并制作了一个函数,如果需要大量随机数,该函数应该可以快速执行。
od
如果您需要大量随机数,则通话费用很高。相反,我只调用它一次,并从/ dev / urandom中存储1024个随机数。当rand
被调用时,最后一个随机数返回和缩放。然后将其从缓存中删除。当缓存为空时,将读取另外1024个随机数。
例:
rand 10; echo $RET
在RET中返回一个介于0和9之间(含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 -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位随机数具有足够的熵,可以容纳0到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 -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
od -An -tu4 -N40 /dev/urandom
将生成10个随机的无符号32位整数,用空格分隔。您可以将其存储在数组中,然后使用。您的代码似乎太过分了。
从/ dev / random或/ dev / urandom字符特殊文件中读取是一种方法。
这些设备在读取时会返回真正的随机数,旨在帮助应用程序软件选择安全密钥进行加密。从由各种随机事件贡献的熵池中提取这样的随机数。{LDD3,Jonathan Corbet,Alessandro Rubini和Greg Kroah-Hartman]
这两个文件是内核随机化的接口,特别是
void get_random_bytes_arch(void* buf, int nbytes)
如果此功能是由硬件实现的(通常是),则从硬件中抽取真正随机的字节,或者从熵池(由事件之间的定时组成,如鼠标和键盘中断以及在SA_SAMPLE_RANDOM中注册的其他中断之间的定时)提取。
dd if=/dev/urandom count=4 bs=1 | od -t d
这可行,但是将不需要的输出从dd
stdout 写入。下面的命令仅给出我需要的整数。通过调整算术扩展的位掩码,我什至可以根据需要获得指定数量的随机位:
me@mymachine:~/$ x=$(head -c 1 /dev/urandom > tmp && hexdump
-d tmp | head -n 1 | cut -c13-15) && echo $(( 10#$x & 127 ))
也许我为时已晚,但是使用jot
Bash在范围内生成随机数又如何呢?
jot -r -p 3 1 0 1
这将生成一个随机(-r
)数字,精度为3个小数位-p
。在这种情况下,您会得到一个介于0和1(1 0 1
)之间的数字。您也可以打印顺序数据。根据手册,随机数的来源是:
如果未指定种子,则通过arc4random(3)获得随机数;如果给出种子,则通过random(3)获得随机数。
基于@ Nelson,@ Barun和@Robert的出色答案,这是一个生成随机数的Bash脚本。
/dev/urandom
,比Bash的内置数字好得多$RANDOM
#!/usr/bin/env bash
digits=10
rand=$(od -A n -t d -N 2 /dev/urandom |tr -d ' ')
num=$((rand % 10))
while [ ${#num} -lt $digits ]; do
rand=$(od -A n -t d -N 1 /dev/urandom |tr -d ' ')
num="${num}$((rand % 10))"
done
echo $num
生成0到n范围内的随机数(带符号的16位整数)。结果设置在$ RAND变量中。例如:
#!/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