2011-01-12 88 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))