2011-01-12 95 views
4

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

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

回答

6

如果你已经TR,头和/ dev/urandom的,你可以这样写:

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

然后,你必须使用,其余运营商摆在0-60范围。

8

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

date +%N 

这不像你需要密码有用的数字在这里。

根据其/bin/sh它的版本,你可以做:

$((date +%N%60))

如果它不支持$(())语法,但你有DC ,你可以尝试:

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

不知道哪个操作系统的版本/bin/sh或者什么 工具可用,很难拿出保证正常工作的解决方案。

+0

可惜的是不注日期的工作,没有直流../bin/sh的--help /bin/sh的--help BusyBox的v1.15.3(2010-07- 21 18:00:33 CEST)多方通话二进制 – Adrian 2011-01-12 23:40:16

2

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

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

我总是得到号码“50” – Adrian 2011-01-12 23:34:40

+1

@Adrian:你必须播种随机数发生器:`awk'BEGIN {srand(); printf(“%d \ n”,rand()* 60)}'`。如果只有一个`BEGIN`子句,则不需要重定向。 – 2011-01-13 04:35:47

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

种子将是0和65535之间,这是不的偶数倍的60,所以分钟0-15具有被选择稍大的机会的ob,但差异可能是不重要的。

如果你想做到尽善尽美,用“OD - 一个-N1 -tu1”和循环,直到值小于240

测试与busybox的OD。每当产生数由0开始,但有其他位数大于7

0

马可的回答会失败,因为它被解释为八进制,我建议:

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 
1

我知道这个职位是旧的,但建议的答案是不产生均匀无偏的随机数。该接受的答案基本上是这样的:

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

这个建议的问题是,从/dev/urandom选择一个3位数,范围为0-999,共1000号。但是,千分之六十不均匀。因此,你会偏向产生0-959,稍微超过960-999。

第二个答案,而创造性的使用纳秒从你的时钟,从相同的偏颇做法受到影响:

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

范围为纳秒是0-999,999,999,为1个十亿的数字。所以,如果你将这个结果除以60,那么你将再次偏向产生0-999,999,959,略多于999,999,960-999,999,999。

所有其余的答案是相同的偏见不均匀的一代。

要生成0-59范围内的无偏差统一随机数(我假设他的意思是,而不是0-60,如果他试图随机化crontab(1)条目),我们需要强制输出为一个倍数60.

首先,我们将随机生成一个32位的数字从0到4294967295:

% 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)) 

把一切一起复制/粘贴goodnees:

#!/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))