Случайное число между диапазоном в оболочке - PullRequest
6 голосов
/ 12 января 2011

Как я могу сгенерировать случайное число от 0 до 60 в sh (/ bin / sh, а не bash)?Это сателлитная коробка, в ней нет переменной $RANDOM и других товароввремя.

Ответы [ 6 ]

8 голосов
/ 13 января 2011

Если у вас есть tr, head и / dev / urandom, вы можете написать это:

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

Затем вы должны использовать оператор остатка, чтобы установить диапазон 0-60.

8 голосов
/ 12 января 2011

Как насчет использования наносекунд системного времени?

date +%N

Здесь вам не нужны криптографически полезные числа.

В зависимости от версии /bin/sh,Вы можете сделать:

$ ((date +%N% 60))

Если он не поддерживает синтаксис $(()), но у вас есть dc, вы можете попробовать:

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

Не зная, какая операционная система, версия /bin/sh или какие инструменты доступны, трудно найти решение, гарантирующее работу.

2 голосов
/ 12 апреля 2017

Я знаю, что этот пост старый, но предлагаемые ответы не генерируют единообразные несмещенные случайные числа.Принятый ответ по существу таков:

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

Проблема с этим предложением состоит в том, что при выборе трехзначного числа из /dev/urandom диапазон составляет от 0 до 999, то есть всего 1000 чисел.Тем не менее, 1000 не делится на 60 равномерно.Таким образом, вы будете смещены в сторону генерации 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-60, если вы добавите 1).

Осталось только убедиться, что мой номер находится в диапазоне от 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))
2 голосов
/ 13 января 2011

У тебя есть awk?Вы можете вызвать функцию rand () в awk.Например:

awk 'BEGIN { printf("%d\n",rand()*60)  }' < /dev/null
0 голосов
/ 09 февраля 2016

Ответ Марко не будет получен всякий раз, когда сгенерированное число начинается с 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
0 голосов
/ 13 января 2011
value=`od -An -N2 -tu2 /dev/urandom`
minutes=`expr $value % 60`

Начальное число будет между 0 и 65535, что не кратно 60, поэтому минут 0-15 имеют немного больший шанс выбора, но расхождение, вероятно, не важно.

Если вы хотите достичь совершенства, используйте «od -An -N1 -tu1» и повторяйте, пока значение не станет меньше 240.

Протестировано с занятым od.

...