sh之间的随机数

我怎么能产生0-60之间的sh(/ bin / sh,而不是bash)的随机数? 这是一个卫星箱,没有$RANDOMvariables,和其他货物[cksum,od(od -vAn -N4 -tu4 </ dev / urandom)]。

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

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

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

那么你必须使用余数运算符来放置0-60的范围。

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

 date +%N 

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

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

$(( date +%N %60))

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

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

在不知道哪个操作系统, /bin/sh版本或者哪些工具可用的情况下,很难想出一个可以保证工作的解决方案。

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

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

我知道这个帖子是旧的,但建议的答案是不会产生统一的无偏倚随机数字。 接受的答案基本上是这样的:

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

这个建议的问题是,通过从/dev/urandom选择一个3位数字,范围是0-999,总共有1,000个数字。 但是,千分之六十不均匀。 因此,你会偏向产生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-60,如果你加1)发电机。

唯一要做的就是确保我的号码在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)) 
  value =`od -An -N2 -tu2 / dev / urandom`
分钟=`expr $ value%60` 

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

如果要实现完美,请使用“od -An -N1 -tu1”并循环,直到值小于240。

用busybox测试。

马可的答案将失败,只要生成的数字开始0,并有其他数字大于7,因为它被解释为八进制,我会建议:

 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