Случайное число из диапазона в сценарии Bash

Мне нужно создать случайный номер порта между 2000-65000 из сценария оболочки. Проблема в том, что $RANDOM – это 15-битное число, поэтому я застрял!

PORT=$(($RANDOM%63000+2001)) будет работать хорошо, если бы не ограничение размера.

Есть ли у кого-нибудь пример того, как я могу это сделать, возможно, извлекая что-то из /dev/urandom и получая его в пределах диапазона?

     shuf -i 2000-65000 -n 1 

    Наслаждайтесь!

    Изменить : диапазон включен.

    В Mac OS X и FreeBSD вы также можете использовать jot:

     jot -r 1 2000 65000 

    Согласно странице man bash, $RANDOM распределяется между 0 и 32767; то есть это неподписанное 15-битное значение. Предполагая, что $RANDOM равномерно распределена, вы можете создать равномерно распределенное беззнаковое 30-битное целое число следующим образом:

     $(((RANDOM<<15)|RANDOM)) 

    Поскольку ваш диапазон не равен 2, простая операция по модулю будет только давать вам равномерное распределение, но с 30-битным диапазоном ввода и диапазоном вывода менее 16 бит, как у вас в вашем случае, это должно быть действительно достаточно близко:

     PORT=$(( ((RANDOM<<15)|RANDOM) % 63001 + 2000 )) 

    и вот один с Python

     randport=$(python -S -c "import random; print random.randrange(2000,63000)") 

    и один с awk

     awk 'BEGIN{srand();print int(rand()*(63000-2000))+2000 }' 

    Самый простой общий способ, который приходит на ум, – это perl one-liner:

     perl -e 'print int(rand(65000-2000)) + 2000' 

    Вы всегда можете просто использовать два номера:

     PORT=$(($RANDOM + ($RANDOM % 2) * 32768)) 

    Вам все равно придется клипать в ваш диапазон. Это не общий метод случайных чисел n-бит, но он будет работать для вашего дела, и все это внутри bash.

    Если вы хотите быть действительно симпатичным и читать из / dev / urandom, вы можете сделать это:

     od -A n -N 2 -t u2 /dev/urandom 

    Это будет читать два байта и печатать их как unsigned int; вам все равно придется делать клиппинг.

    Вот еще один. Я думал, что это сработает почти во всем, но случайный вариант сортировки недоступен в моей панели centos на работе.

      seq 2000 65000 | sort -R | head -n 1 

    Если вы не эксперт по bash и не хотите, чтобы это превратилось в переменную в сценарии bash на базе Linux, попробуйте следующее:

    VAR=$(shuf -i 200-700 -n 1)

    Это дает вам диапазон от 200 до 700 в $VAR , включительно.

    В документации Bash говорится, что каждый раз, когда указывается $RANDOM , возвращается случайное число от 0 до 32767. Если мы суммируем две последовательные ссылки, мы получаем значения от 0 до 65534, что покрывает желаемый диапазон возможностей 63001 для случайного числа между 2000 и 65000.

    Чтобы настроить его на точный диапазон, мы используем сумму modulo 63001, которая даст нам значение от 0 до 63000. Это, в свою очередь, просто требует прироста к 2000 году, чтобы обеспечить желаемое случайное число в диапазоне от 2000 до 65000. Это может быть резюмируется следующим образом:

     port=$((((RANDOM + RANDOM) % 63001) + 2000)) 

    тестирование

     # Generate random numbers and print the lowest and greatest found test-random-max-min() { max=2000 min=65000 for i in {1..10000}; do port=$((((RANDOM + RANDOM) % 63001) + 2000)) echo -en "\r$port" [[ "$port" -gt "$max" ]] && max="$port" [[ "$port" -lt "$min" ]] && min="$port" done echo -e "\rMax: $max, min: $min" } # Sample output # Max: 64990, min: 2002 # Max: 65000, min: 2004 # Max: 64970, min: 2000 

    Правильность расчета

    Вот полный и грубый тест для правильности вычисления. Эта программа просто пытается случайным образом генерировать все 63001 различные возможности, используя подсчитанный расчет. Параметр --jobs должен --jobs его работу, но он не является детерминированным (общее количество создаваемых возможностей может быть ниже 63001).

     test-all() { start=$(date +%s) find_start=$(date +%s) total=0; ports=(); i=0 rm -f ports/ports.* ports.* mkdir -p ports while [[ "$total" -lt "$2" && "$all_found" != "yes" ]]; do port=$((((RANDOM + RANDOM) % 63001) + 2000)); i=$((i+1)) if [[ -z "${ports[port]}" ]]; then ports["$port"]="$port" total=$((total + 1)) if [[ $((total % 1000)) == 0 ]]; then echo -en "Elapsed time: $(($(date +%s) - find_start))s \t" echo -e "Found: $port \t\t Total: $total\tIteration: $i" find_start=$(date +%s) fi fi done all_found="yes" echo "Job $1 finished after $i iterations in $(($(date +%s) - start))s." out="ports.$1.txt" [[ "$1" != "0" ]] && out="ports/$out" echo "${ports[@]}" > "$out" } say-total() { generated_ports=$(cat "[email protected]" | tr ' ' '\n' | \sed -E s/'^([0-9]{4})$'/'0\1'/) echo "Total generated: $(echo "$generated_ports" | sort | uniq | wc -l)." } total-single() { say-total "ports.0.txt"; } total-jobs() { say-total "ports/"*; } all_found="no" [[ "$1" != "--jobs" ]] && test-all 0 63001 && total-single && exit for i in {1..1000}; do test-all "$i" 40000 & sleep 1; done && wait && total-jobs 

    Для определения того, сколько итераций необходимо для получения заданной вероятности p/q всех 63001 возможных возможностей, я считаю, что мы можем использовать приведенное ниже выражение. Например, здесь вычисление вероятности больше 1/2 , а здесь для более 9/10 .

    выражение

    $RANDOM – это число от 0 до 32767. Требуется порт между 2000 и 65000. Это 63001 возможных портов. Если мы придерживаемся значений $RANDOM + 2000 между 2000 и 33500 , мы охватываем ряд портов 31501. Если мы перевернем монету и затем условно добавим 31501 к результату, мы сможем получить больше портов с 33501 до 65001 . Тогда, если мы просто отбросим 65001, мы получим точный охват, который, по всей видимости, с равномерным распределением вероятности для всех портов.

     random-port() { while [[ not != found ]]; do # 2000..33500 port=$((RANDOM + 2000)) while [[ $port -gt 33500 ]]; do port=$((RANDOM + 2000)) done # 2000..65001 [[ $((RANDOM % 2)) = 0 ]] && port=$((port + 31501)) # 2000..65000 [[ $port = 65001 ]] && continue echo $port break done } 

    тестирование

     i=0 while true; do i=$((i + 1)) printf "\rIteration $i..." printf "%05d\n" $(random-port) >> ports.txt done # Then later we check the distribution sort ports.txt | uniq -c | sort -r 

    Вы можете сделать это

     cat /dev/urandom|od -N2 -An -i|awk -vf=2000 -vr=65000 '{printf "%i\n", f + r * $1 / 65536}' 

    Если вам нужна дополнительная информация, см. Генератор случайных чисел Shell Script .

    Или на OS-X для меня работает следующее:

     $ gsort --random-sort 

    То же самое с rubyом:

     ZZZ=$(ruby -e 'puts rand(20..65)') echo $ZZZ #=> 56 

    PORT=$(($RANDOM%63000+2001)) близок к тому, что вы хотите, я думаю.

    PORT=$(($RANDOM$RANDOM$RANDOM%63000+2001)) получает ограничение по размеру, которое вас беспокоит. Поскольку bash не делает различий между числовой переменной и строковой переменной, это работает отлично. «Число» $RANDOM может быть объединено как строка, а затем использовано как число в расчете. Удивительно!

    Вы можете получить случайное число через urandom

    head -200 /dev/urandom | cksum

    Вывод:

    3310670062 52870

    Чтобы получить одну часть вышеуказанного номера.

    head -200 /dev/urandom | cksum | cut -f1 -d " "

    Тогда выход

    3310670062

    Чтобы удовлетворить ваши требования,

    head -200 /dev/urandom |cksum | cut -f1 -d " " | awk '{print $1%63000+2001}'

    Так я обычно генерирую случайные числа. Затем я использую «NUM_1» в качестве переменной для используемого номера порта. Вот короткий пример скрипта.

     #!/bin/bash clear echo 'Choose how many digits you want for port# (1-5)' read PORT NUM_1="$(tr -dc '0-9'  
    Interesting Posts

    Как изменить размер окна, чтобы он был больше физического экрана?

    Как изменить цвет строки состояния в android

    Выберите копию и вставьте в терминал mac или ubuntu без использования мыши

    Как исправить ошибку загрузчика Windows XP, когда BOOTCFG, FIXBOOT и FIXMBR ничего не делают?

    Что делает ?

    Как изменить лицензионный ключ Visual Studio 2012,2013 или 2015?

    Можно добавить дополнительные поля в дополнительную таблицу @ManyToMany Hibernate?

    Как удалить защиту из файла PDF?

    Использование 100% всех ядер с модулем многопроцессорности

    Почему зарядка мобильных устройств через USB настолько медленная?

    Интерфейсы выводятся из System.Object? C # spec говорит «да», Эрик говорит «нет», реальность говорит «нет»

    Строка POST для приложения ASP.NET Web Api – возвращает значение null

    Проверка на стороне клиента ASP.NET MVC 3 с параметрами

    Как узнать файлы «.automaticDestinations-ms», к которым относится приложение?

    Отсутствует System.web.mvc

    Давайте будем гением компьютера.