Ich muss eine zufällige Portnummer zwischen 2000-65000
aus einem Shell-Skript generieren . Das Problem ist $RANDOM
eine 15-Bit-Zahl, also stecke ich fest!
PORT=$(($RANDOM%63000+2001))
würde gut funktionieren, wenn es nicht für die Größenbeschränkung wäre.
Hat jemand ein Beispiel dafür, wie ich das tun kann, vielleicht indem ich etwas extrahiere /dev/urandom
und es in einen Bereich bringe?
shuf
ist relativ neu - ich habe es in den letzten Jahren auf Ubuntu-Systemen gesehen, aber nicht auf dem aktuellen RHEL / CentOS.shuf
es tatsächlich die gesamte Eingabe permutiert. Dies macht es zu einer schlechten Wahl, wenn Sie die Zufallszahlen sehr häufig generieren.time for i in {1..1000}; do shuf -i 0-$end -n 1000 > /dev/null; done
und der Vergleichend=1
mitend=65535
eine Verbesserung um 25% für den kürzeren Bereich, der sich auf eine Differenz von ungefähr 4 Sekunden über eine Million Iterationen belief. Und es ist viel schneller, als die Bash-Berechnung des OP millionenfach durchzuführen.-n 1
zeigte vernachlässigbare Zeitunterschiede, auch mitend=4000000000
. Gut zu wissen,shuf
funktioniert klug, nicht schwer :-)Unter Mac OS X und FreeBSD können Sie auch jot verwenden:
quelle
jot
ist die Verteilung für das Minimum und Maximum des Intervalls ungerecht (dh 2000 und 65000). Mit anderen Worten, Min und Max werden weniger häufig generiert. Weitere Informationen und eine Problemumgehung finden Sie in meiner Antwort .jot
ist auch in den meisten GNU / Linux-Distributionen verfügbarLaut Bash-Manpage
$RANDOM
ist zwischen 0 und 32767 verteilt; Das heißt, es ist ein vorzeichenloser 15-Bit-Wert. Unter der Annahme, dass die$RANDOM
Verteilung gleichmäßig ist, können Sie eine gleichmäßig verteilte vorzeichenlose 30-Bit-Ganzzahl wie folgt erstellen:Da Ihr Bereich keine Potenz von 2 ist, erhalten Sie mit einer einfachen Modulo-Operation nur eine nahezu gleichmäßige Verteilung, jedoch mit einem 30-Bit-Eingangsbereich und einem weniger als 16-Bit-Ausgabebereich, wie Sie es in Ihrem Fall getan haben. das sollte wirklich nah genug sein:
quelle
$RANDOM
ist nicht immer in allen Shells verfügbar. Auf der Suche nach einer anderen Lösung$RANDOM
zweimal verweist . Bei Shells, die dies unterstützen$RANDOM
, wird bei jedem Verweis ein neuer Wert generiert. Dieser Code füllt also die Bits 0 bis 14 mit einem$RANDOM
Wert und die Bits 15 bis 29 mit einem anderen. Vorausgesetzt, es$RANDOM
ist einheitlich und unabhängig, deckt dies alle Werte von 0 bis 2 ** 30-1 ab, ohne etwas zu überspringen.und hier ist einer mit Python
und einer mit awk
quelle
RANDOM
wird von POSIX nicht garantiert,-S
Option führt zuImportError: No module named random
. Funktioniert, wenn ich das entferne. Ich bin mir nicht sicher, was Ghostdog dafür vorhatte.python -S -c "import random; print random.randrange(2000,63000)"
scheint gut zu funktionieren. Wenn ich jedoch versuche, eine Zufallszahl zwischen 1 und 2 zu erhalten, bekomme ich anscheinend immer 1 ... Gedanken?Der einfachste allgemeine Weg, der mir in den Sinn kommt, ist ein Perl-Einzeiler:
Sie können immer nur zwei Zahlen verwenden:
Sie müssen immer noch an Ihrem Bereich befestigen. Es ist keine allgemeine n-Bit-Zufallszahlenmethode, aber sie funktioniert für Ihren Fall und ist alles in Bash.
Wenn Sie wirklich süß sein und aus / dev / urandom lesen möchten, können Sie dies tun:
Das liest zwei Bytes und druckt sie als vorzeichenloses int; Sie müssen noch Ihren Ausschnitt machen.
quelle
awk
Version einer anderen AntwortWenn Sie kein Bash-Experte sind und dies in eine Variable in einem Linux-basierten Bash-Skript umwandeln möchten, versuchen Sie Folgendes:
VAR=$(shuf -i 200-700 -n 1)
Damit haben Sie einen Bereich von 200 bis
$VAR
einschließlich 700 .quelle
Hier ist ein anderes. Ich dachte, es würde bei fast allem funktionieren, aber die zufällige Option von sort ist auf meiner Centos-Box bei der Arbeit nicht verfügbar.
quelle
sort -R
ist auch unter OS X nicht verfügbar.$RANDOM
ist eine Zahl zwischen 0 und 32767. Sie möchten einen Port zwischen 2000 und 65000. Dies sind 63001 mögliche Ports. Wenn wir uns an Werte$RANDOM + 2000
zwischen 2000 und 33500 halten , decken wir einen Bereich von 31501 Ports ab. Wenn wir eine Münze werfen und dann bedingt 31501 zum Ergebnis hinzufügen, können wir mehr Ports von 33501 bis 65001 erhalten . Wenn wir dann nur 65001 fallen lassen, erhalten wir genau die erforderliche Abdeckung mit einer einheitlichen Wahrscheinlichkeitsverteilung für alle Ports, wie es scheint.Testen
quelle
Du kannst das
Weitere Informationen finden Sie unter Shell Script Random Number Generator .
quelle
Gleiches gilt für Rubin:
quelle
In der Bash-Dokumentation heißt es, dass bei jedem
$RANDOM
Verweis eine Zufallszahl zwischen 0 und 32767 zurückgegeben wird. Wenn wir zwei aufeinanderfolgende Referenzen summieren, erhalten wir Werte von 0 bis 65534, was den gewünschten Bereich von 63001 Möglichkeiten für eine Zufallszahl zwischen 2000 und 65000 abdeckt.Um es auf den genauen Bereich einzustellen, verwenden wir die Summe modulo 63001, die einen Wert von 0 bis 63000 ergibt. Dies erfordert wiederum nur ein Inkrement um 2000, um die gewünschte Zufallszahl zwischen 2000 und 65000 bereitzustellen. Dies kann sein wie folgt zusammengefasst:
Testen
Richtigkeit der Berechnung
Hier ist ein vollständiger Brute-Force-Test für die Richtigkeit der Berechnung. Dieses Programm versucht nur, alle 63001 verschiedenen Möglichkeiten zufällig unter Verwendung der zu testenden Berechnung zu generieren. Der
--jobs
Parameter sollte die Ausführung beschleunigen, ist jedoch nicht deterministisch (die Gesamtzahl der generierten Möglichkeiten kann unter 63001 liegen).Um zu bestimmen, wie viele Iterationen erforderlich sind, um eine bestimmte Wahrscheinlichkeit
p/q
zu erhalten, dass alle 63001-Möglichkeiten generiert wurden, können wir meines Erachtens den folgenden Ausdruck verwenden. Hier ist zum Beispiel die Berechnung für eine Wahrscheinlichkeit größer als 1/2 und hier für mehr als 9/10 .quelle
$RANDOM
ist eine ganze Zahl . Mit Ihrem "Trick" gibt es viele Werte, die niemals erreicht werden.-1
.$RANDOM
stattdessen zwei Zugriffe auf summieren und dies nicht in eine Multiplikation mit zwei umgestalten, da$RANDOM
sich dies bei jedem Zugriff ändern soll. Ich habe die Antwort mit der Summenversion aktualisiert.RANDOM+RANDOM
Sie dies tun , erhalten Sie keine gleichmäßige Verteilung der Zufallszahlen zwischen 0 und 65534.Oder unter OS-X funktioniert für mich Folgendes:
quelle
PORT=$(($RANDOM%63000+2001))
ist nah an dem, was du willst, denke ich.PORT=$(($RANDOM$RANDOM$RANDOM%63000+2001))
umgeht die Größenbeschränkung, die Sie stört. Da bash nicht zwischen einer Zahlenvariablen und einer Zeichenfolgenvariablen unterscheidet, funktioniert dies einwandfrei. Die "Zahl"$RANDOM
kann wie eine Zeichenfolge verkettet und dann als Zahl in einer Berechnung verwendet werden. Tolle!quelle
x=$(( $n%63000 )
ist ungefähr ähnlich zux=$(( $n % 65535 )); if [ $x -gt 63000 ]; then x=63000
.Sie können die Zufallszahl durch bekommen
urandom
head -200 /dev/urandom | cksum
Ausgabe:
3310670062 52870
Um den einen Teil der obigen Nummer abzurufen.
head -200 /dev/urandom | cksum | cut -f1 -d " "
Dann ist die Ausgabe
3310670062
Um Ihre Anforderungen zu erfüllen,
head -200 /dev/urandom |cksum | cut -f1 -d " " | awk '{print $1%63000+2001}'
quelle
So generiere ich normalerweise Zufallszahlen. Dann verwende ich "NUM_1" als Variable für die von mir verwendete Portnummer. Hier ist ein kurzes Beispielskript.
quelle