Я знаю, что этот пост старый, но предлагаемые ответы не генерируют единообразные несмещенные случайные числа.Принятый ответ по существу таков:
% 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))