如何在sh中生成0-60之间的随机数(/ bin / sh,而不是bash)?这是一个卫星箱,没有$RANDOM
变量,还有其他商品[cksum,od(od -vAn -N4 -tu4< / dev / urandom)]。
我想随机化一个crontab作业的时间。
答案 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 '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