shell中的范围之间的随机数

时间:2011-01-12 20:43:56

标签: linux shell random

如何在sh中生成0-60之间的随机数(/ bin / sh,而不是bash)?这是一个卫星箱,没有$RANDOM变量,还有其他商品[cksum,od(od -vAn -N4 -tu4< / dev / urandom)]。

我想随机化一个crontab作业的时间。

6 个答案:

答案 0 :(得分:8)

如何使用纳秒的系统时间?

date +%N

这不像你需要加密有用的数字。

根据/bin/sh的版本,您可以执行以下操作:

$((date +%N%60))

如果它不支持$(())语法,但您有dc,则可以尝试:

dc -e `date +%N`' 60 % p'

不知道哪个操作系统,版本/bin/sh或什么 有工具可用,很难找到一个可以保证工作的解决方案。

答案 1 :(得分:7)

如果你有tr,head和/ dev / urandom,你可以这样写:

tr -cd 0-9 </dev/urandom | head -c 3

然后你必须使用余数运算符放入0-60范围。

答案 2 :(得分:2)

你有awk吗?你可以调用awk的rand()函数。例如:

awk 'BEGIN { printf("%d\n",rand()*60)  }' < /dev/null

答案 3 :(得分:2)

我知道这篇文章很老,但建议的答案并没有产生统一的无偏随机数。接受的答案基本上是这样的:

% echo $(( $(tr -cd 0-9 </dev/urandom | head -c 3) % 60))

此建议的问题在于,通过从/dev/urandom中选择一个3位数字,范围为0-999,总共1,000个数字。但是,1000不均匀分为60。因此,您将偏向于生成0-959,略高于960-999。

第二个答案虽然在时钟中使用纳秒时具有创造性,却遭受同样的偏见:

% echo $(( $(date +%N) % 60 ))

纳秒的范围是0-999,999,999,这是10亿个数字。所以,如果你将结果除以60,你将再次偏向于生成0-999,999,959,略高于999,999,960-999,999,999。

所有其他答案都是相同的 - 不均匀的一代。

要产生0-59范围内的无偏均匀随机数(我认为他的意思是指而不是0-60,如果他试图随机化一个crontab(1)条目),我们需要强制输出到是60的倍数。

首先,我们将生成0到4294967295之间的随机32位数字:

% RNUM=$(od -An -N4 -tu2 /dev/urandom | awk '{print $1}')

现在我们将强制我们的范围介于$ MIN和4294967295之间,这是60的倍数:

% MIN=$((2**32 % 60)) # 16

这意味着:

4294967296 - 16 = 4294967280
4294967280 / 60 = 71582788.0

换句话说,我的[16,4294967295]的范围恰好是60的倍数。因此,我在该范围内生成的每个数字,然后除以60,将与任何其他数字一样可能。因此,我有一个无偏的数字0-59生成器(如果加1则为1-60)。

唯一要做的就是确保我的号码在16到4294967295之间。如果我的号码小于16,那么我需要生成一个新号码:

% while [ $RNUM -lt $MIN ]; do RNUM=$(od -An -N1 -tu2 /dev/urandom); done
% MINUTE=$(($RNUM % 60))

复制/粘贴好东西的所有东西:

#!/bin/bash
RNUM=$(od -An -N4 -tu2 /dev/urandom | awk '{print $1}')
MIN=$((2**32 % 60))
while [ $RNUM -lt $MIN ]; do RNUM=$(od -An -N1 -tu2 /dev/urandom); done
MINUTE=$(($RNUM % 60))

答案 4 :(得分:0)

value=`od -An -N2 -tu2 /dev/urandom`
minutes=`expr $value % 60`

种子将在0到65535之间,这不是60的偶数倍,因此0-15分钟的选择机会略高,但差异可能并不重要。

如果你想达到完美,请使用“od -An -N1 -tu1”并循环,直到值小于240.

使用busybox od进行测试。

答案 5 :(得分:0)

每当生成的数字从0开始并且其他数字大于7时,Marco的答案就会失败,因为它被解释为八进制,我建议:

tr -cd 0-9 </dev/urandom | head -c 4 | sed -e 's/^00*//

特别是如果您想进一步处理它,例如建立范围:

RANDOM=`tr -cd 0-9 </dev/urandom | head -c 4 | sed -e 's/^00*//'`
RND50=$((($RANDOM%50)+1))   // random number between 1 and 50