谷歌搜索了一下之后,我找不到一种简单的方法来使用shell命令来生成一个包含在特定范围内的随机十进制整数,该范围介于最小值和最大值之间。
我了解/dev/random
,/dev/urandom
和$RANDOM
,但这些都不可以做什么,我需要。
还有其他有用的命令,还是使用先前数据的方法?
谷歌搜索了一下之后,我找不到一种简单的方法来使用shell命令来生成一个包含在特定范围内的随机十进制整数,该范围介于最小值和最大值之间。
我了解/dev/random
,/dev/urandom
和$RANDOM
,但这些都不可以做什么,我需要。
还有其他有用的命令,还是使用先前数据的方法?
Answers:
在POSIX工具箱中,您可以使用awk
:
awk -v min=5 -v max=10 'BEGIN{srand(); print int(min+rand()*(max-min+1))}'
千万不能使用它作为源生成口令或例如秘密数据,与大多数awk
实现中,数量可以很容易地根据该命令运行的时间猜测。
对于许多awk
实现,该命令在同一秒内运行两次通常会为您提供相同的输出。
x=$(awk -v min=$min_var -v max=$max_var 'BEGIN{srand(); printf("%.2d", int(min+rand()*(max-min+1)))}')
awk -v min=5 -v max=10 -v seed="$(od -An -N4 -tu4 /dev/urandom)" 'BEGIN{srand(seed+0); print int(min+rand()*(max-min+1))}'
。您可以使用$RANDOM
代替,od ... /dev/random
但是您的种子值在0到32767的相对较小范围内,因此随着时间的推移,您的输出中可能会出现明显的重复。
在BSD和OSX上,您可以使用jot返回-r
从时间间隔min
到的单个随机()数字(max
含)。
$ min=5
$ max=10
$ jot -r 1 $min $max
不幸的是,随机生成的数字的范围和分布受以下事实的影响:jot在内部使用双精度浮点算术并对输出格式使用printf(3),这会导致舍入和截断问题。因此,间隔min
和max
的生成频率较低,如下所示:
$ jot -r 100000 5 10 | sort -n | uniq -c
9918 5
20176 6
20006 7
20083 8
19879 9
9938 10
在OS X 10.11(El Capitan)上,此问题似乎已解决:
$ jot -r 100000 5 10 | sort -n | uniq -c
16692 5
16550 6
16856 7
16579 8
16714 9
16609 10
和...
$ jot -r 1000000 1 10 | sort -n | uniq -c
100430 1
99965 2
99982 3
99796 4
100444 5
99853 6
99835 7
100397 8
99588 9
99710 10
对于旧版本的OS X,幸运的是,有几种解决方法。一种是使用printf(3)整数转换。唯一的警告是最大间隔现在变为max+1
。通过使用整数格式,我们可以在整个时间间隔内公平分配:
$ jot -w %i -r 100000 5 11 | sort -n | uniq -c
16756 5
16571 6
16744 7
16605 8
16683 9
16641 10
最后,为了使用解决方法公平地掷骰子,我们有:
$ min=5
$ max_plus1=11 # 10 + 1
$ jot -w %i -r 1 $min $max_plus1
参见jot(1)以获得更多的数学知识和格式细节,以及更多示例。
您可以通过获得随机数 urandom
head -200 /dev/urandom | cksum
输出:
3310670062 52870
要检索上述编号的一部分。
head -200 /dev/urandom | cksum | cut -f1 -d " "
然后输出是
3310670062
head -200
(或者其等效POSIX head -n 100
)返回前200 行的/dev/urandom
。/dev/urandom
不是文本文件,该命令可以从200个字节(全为0x0a,ASCII中为LF)返回到无穷大(如果从不返回0xa字节),但最有可能介于45k和55k之间。cksum返回一个32位数字,因此从中获取4个以上的字节毫无意义/dev/urandom
。
要生成介于5到10(包括两者)之间的随机整数变量,请使用
echo $(( RANDOM % (10 - 5 + 1 ) + 5 ))
%
作为模运算符。
将随机变量$RANDOM
转换为特定范围可能有更好的方法。请勿将其用于加密应用程序,或者在您需要真实,均匀分布的随机变量(例如用于模拟)的情况下。
要完全停留在bash中并使用$ RANDOM变量,但要避免分布不均:
#!/bin/bash
range=10
floor=20
if [ $range -gt 32768 ]; then
echo 'range outside of what $RANDOM can provide.' >&2
exit 1 # exit before entering infinite loop
fi
max_RANDOM=$(( 2**15/$range*$range ))
r=$RANDOM
until [ $r -lt $max_RANDOM ]; do
r=$RANDOM
done
echo $(( r % $range + $floor ))
本示例将提供20到29之间的随机数。
$r
应将其初始化为65535或其他较高的值,以免发生[: -lt: unary operator expected
错误。