Muszę wygenerować losowy numer portu pomiędzy 2000-65000
skryptem powłoki. Problemem jest $RANDOM
15-bitowa liczba, więc utknąłem!
PORT=$(($RANDOM%63000+2001))
działałby ładnie, gdyby nie ograniczenie wielkości.
Czy ktoś ma przykład, w jaki sposób mogę to zrobić, może poprzez wyciągnięcie czegoś /dev/urandom
i umieszczenie go w zasięgu?
shuf
jest stosunkowo nowy - widziałem go na systemach Ubuntu w ciągu ostatnich kilku lat, ale nie na obecnym RHEL / CentOS.shuf
że faktycznie przenika całe dane wejściowe. To sprawia, że jest to zły wybór, jeśli bardzo często generujesz liczby losowe.time for i in {1..1000}; do shuf -i 0-$end -n 1000 > /dev/null; done
i porównującend=1
doend=65535
wykazała poprawę o 25% w przypadku krótszego zasięgu, które wyniosły około 4 sekundy różnicy ponad miliona iteracji. Jest to o wiele szybsze niż wykonywanie obliczenia Bash PO milion razy.-n 1
wykazało znikome różnice czasowe, nawet zend=4000000000
. Dobrze wiedzieć,shuf
działa dobrze , a nie ciężko :-)W systemach Mac OS X i FreeBSD możesz także użyć jot:
źródło
jot
ma niesprawiedliwy rozkład dla minimum i maksimum przedziału (tj. 2000 i 65000). Innymi słowy, min i max będą generowane rzadziej. Zobacz moją odpowiedź, aby uzyskać szczegółowe informacje i obejście.jot
jest również dostępny w większości dystrybucji GNU / LinuxWedług strony podręcznika bash,
$RANDOM
jest on dystrybuowany między 0 a 32767; to jest 15-bitowa wartość bez znaku. Zakładając, że$RANDOM
jest równomiernie rozłożona, możesz utworzyć równomiernie rozłożoną 30-bitową liczbę całkowitą bez znaku w następujący sposób:Ponieważ twój zakres nie jest potęgą 2, prosta operacja modulo da prawie tylko jednolity rozkład, ale z 30-bitowym zakresem wejściowym i mniej niż 16-bitowym zakresem wyjściowym, jak masz w tym przypadku, to naprawdę powinno być wystarczająco blisko:
źródło
$RANDOM
nie zawsze jest dostępna we wszystkich powłokach. Szukasz innego rozwiązania$RANDOM
dwukrotnie. W obsługiwanych powłokach$RANDOM
nowa wartość jest generowana za każdym razem, gdy się do niej odwołuje. Więc ten kod wypełnia bity od 0 do 14 jedną$RANDOM
wartością, a bity od 15 do 29 inną. Zakładając, że$RANDOM
jest jednolity i niezależny, obejmuje to wszystkie wartości od 0 do 2 ** 30-1 bez pomijania czegokolwiek.a oto jeden z Pythonem
i jeden z awk
źródło
RANDOM
POSIX nie gwarantuje,-S
opcji powodujeImportError: No module named random
. Działa, jeśli to usunę. Nie jestem pewien, jaki był zamiar ghostdog.python -S -c "import random; print random.randrange(2000,63000)"
wydaje się działać dobrze. Jednak gdy próbuję uzyskać losową liczbę od 1 do 2, wydaje mi się, że zawsze otrzymuję 1 ... Myśli?Najprostszym ogólnym sposobem, jaki przychodzi mi na myśl, jest perl-one-liner:
Zawsze możesz po prostu użyć dwóch liczb:
Nadal musisz przyciąć swój zasięg. To nie jest ogólna n-bitowa metoda liczb losowych, ale zadziała w twoim przypadku i wszystko jest w środku.
Jeśli chcesz być naprawdę słodki i czytać z / dev / urandom, możesz to zrobić:
To przeczyta dwa bajty i wydrukuje je jako int bez znaku; nadal musisz zrobić wycinek.
źródło
awk
wersji z innej odpowiedziJeśli nie jesteś ekspertem od bashów i chciałeś zamienić to na zmienną w skrypcie bash opartym na Linuksie, spróbuj tego:
VAR=$(shuf -i 200-700 -n 1)
To daje zakres od 200 do 700
$VAR
włącznie.źródło
Oto kolejny. Myślałem, że zadziała na wszystko, ale losowa opcja sortowania nie jest dostępna na moim polu centos w pracy.
źródło
sort -R
nie jest również dostępny w systemie OS X.$RANDOM
jest liczbą od 0 do 32767. Chcesz mieć port między 2000 a 65000. Są to 63001 możliwych portów. Jeśli będziemy trzymać się wartości$RANDOM + 2000
między 2000 a 33500 , omówimy szereg 31501 portów. Jeśli przerzucimy monetę, a następnie warunkowo dodamy 31501 do wyniku, możemy uzyskać więcej portów, od 33501 do 65001 . Jeśli po prostu upuszczymy 65001, otrzymamy dokładnie wymagany zasięg, z jednolitym rozkładem prawdopodobieństwa dla wszystkich portów, wydaje się.Testowanie
źródło
Możesz to zrobić
Jeśli potrzebujesz więcej informacji, zobacz Generator liczb losowych w skrypcie powłoki .
źródło
To samo z rubinem:
źródło
Dokumentacja Bash mówi, że przy każdym
$RANDOM
odwołaniu zwracana jest losowa liczba od 0 do 32767. Jeśli zsumujemy dwa kolejne odniesienia, otrzymamy wartości od 0 do 65534, co obejmuje pożądany zakres 63001 możliwości dla liczby losowej między 2000 a 65000.Aby dostosować go do dokładnego zakresu, używamy sumy modulo 63001, która da nam wartość od 0 do 63000. To z kolei potrzebuje tylko przyrostu o 2000, aby zapewnić pożądaną liczbę losową, między 2000 a 65000. Może to być podsumowane w następujący sposób:
Testowanie
Poprawność obliczeń
Oto pełny, brutalny test poprawności obliczeń. Ten program próbuje po prostu losowo wygenerować wszystkie 63001 różnych możliwości, wykorzystując testowane obliczenia. Ten
--jobs
parametr powinien przyspieszyć jego działanie, ale nie jest deterministyczny (suma wygenerowanych możliwości może być mniejsza niż 63001).Aby ustalić, ile iteracji jest potrzebnych do uzyskania danego prawdopodobieństwa
p/q
wygenerowania wszystkich 63001 możliwości, uważam, że możemy użyć poniższego wyrażenia. Na przykład tutaj jest obliczenie dla prawdopodobieństwa większego niż 1/2 , a tutaj dla większego niż 9/10 .źródło
$RANDOM
jest liczbą całkowitą . Dzięki „sztuczce” istnieje wiele wartości, które nigdy nie zostaną osiągnięte.-1
.$RANDOM
Zamiast tego musimy zsumować dwa dostępy i nie przekształcać tego w mnożenie przez dwa, ponieważ$RANDOM
ma się to zmieniać przy każdym dostępie. Zaktualizowałem odpowiedź o wersję sumaryczną.RANDOM+RANDOM
nie uzyskasz jednolitego rozkładu liczb losowych między 0 a 65534.Lub w systemie OS-X następujące funkcje działają dla mnie:
źródło
PORT=$(($RANDOM%63000+2001))
myślę, że jest blisko tego, czego chcesz.PORT=$(($RANDOM$RANDOM$RANDOM%63000+2001))
omija ograniczenie rozmiaru, które Cię niepokoi. Ponieważ bash nie rozróżnia między zmienną liczbową a zmienną łańcuchową, działa to doskonale. „Liczba”$RANDOM
może być łączona jak ciąg, a następnie używana jako liczba w obliczeniach. Niesamowity!źródło
x=$(( $n%63000 )
jest z grubsza podobny dox=$(( $n % 65535 )); if [ $x -gt 63000 ]; then x=63000
.Możesz uzyskać losową liczbę poprzez
urandom
head -200 /dev/urandom | cksum
Wynik:
3310670062 52870
Aby pobrać jedną część powyższego numeru.
head -200 /dev/urandom | cksum | cut -f1 -d " "
Następnie wyjście jest
3310670062
Aby spełnić twoje wymagania,
head -200 /dev/urandom |cksum | cut -f1 -d " " | awk '{print $1%63000+2001}'
źródło
W ten sposób zwykle generuję liczby losowe. Następnie używam „NUM_1” jako zmiennej dla używanego numeru portu. Oto krótki przykładowy skrypt.
źródło