Antworten:
Verwenden Sie $RANDOM
. Es ist oft nützlich in Kombination mit einfacher Shell-Arithmetik. Zum Beispiel, um eine Zufallszahl zwischen 1 und 10 (einschließlich) zu generieren:
$ echo $((1 + RANDOM % 10))
3
Der eigentliche Generator ist in variables.c
der Funktion brand()
. Ältere Versionen waren ein einfacher Lineargenerator. Version 4.0 von bash
verwendet einen Generator mit einem Zitat aus einem Artikel von 1985, was vermutlich bedeutet, dass es eine anständige Quelle für Pseudozufallszahlen ist. Ich würde es nicht für eine Simulation verwenden (und schon gar nicht für Krypto), aber es ist wahrscheinlich ausreichend für grundlegende Skriptaufgaben.
Wenn Sie etwas tun, das ernsthafte Zufallszahlen erfordert, können Sie diese verwenden /dev/random
oder /dev/urandom
wenn sie verfügbar sind:
$ dd if=/dev/urandom count=4 bs=1 | od -t d
$RANDOM % 10
sind 8 und 9 messbar (wenn auch geringfügig) weniger wahrscheinlich als 0-7, selbst wenn $RANDOM
es sich um eine robuste Quelle für zufällige Daten handelt.
$RANDOM
‚s - Bereich ist 0-32767
die Zahl 0
- 7
Karte zu 3277
verschiedenen möglichen Eingaben, aber 8
und 9
kann nur hergestellt werden 3276
unterschiedliche Weise (da 32768
und 32769
sind nicht möglich). Dies ist ein kleines Problem bei schnellen Hacks, bedeutet jedoch, dass das Ergebnis nicht einheitlich zufällig ist. Zufällige Bibliotheken wie Java Random
bieten Funktionen, um eine einheitliche Zufallszahl im angegebenen Bereich korrekt zurückzugeben, anstatt einfach eine nicht teilbare Zahl zu ändern.
Bitte sehen Sie $RANDOM
:
$RANDOM
ist eine interne Bash-Funktion (keine Konstante), die eine pseudozufällige Ganzzahl im Bereich von 0 bis 32767 zurückgibt. Sie sollte nicht zum Generieren eines Verschlüsselungsschlüssels verwendet werden.
32767
eine besondere Bedeutung?
32767
ist 2^16 / 2 - 1
die Obergrenze für eine vorzeichenbehaftete 16-Bit-Ganzzahl.
2^15 - 1
? Es ist gleichwertig, also bin ich nur neugierig, ob mir ein Kontext fehlt?
Sie können auch shuf verwenden (erhältlich in coreutils).
shuf -i 1-100000 -n 1
shuf -i 1-10 -n 1: syntax error in expression (error token is "1-10 -n 1")
$var
anstelle des Bereichsende hinzu, wie var=100 && shuf -i 1-${var} -n 1
-n
. ZB Generiere 5 Zufallszahlen zwischen 1 und 100 :shuf -i 1-100 -n 5
shuf -i 1-10 -n 10
Sie alle Zahlen von 1 bis 10 genau eins. Wenn Sie angeben, erhalten -n 15
Sie immer noch nur einmal genau diese 10 Zahlen. Das ist wirklich nur Mischen, keine Zufallszahlen erzeugen.
Versuchen Sie dies aus Ihrer Shell:
$ od -A n -t d -N 1 /dev/urandom
Gibt hier an, -t d
dass das Ausgabeformat dezimal signiert werden soll. -N 1
sagt, ein Byte von zu lesen /dev/urandom
.
od -A n -t d -N 1 /dev/urandom |tr -d ' '
Sie können auch eine Zufallszahl von awk erhalten
awk 'BEGIN {
# seed
srand()
for (i=1;i<=1000;i++){
print int(1 + rand() * 100)
}
}'
srand()
der Startwert die aktuelle CPU-Zeit ist. Wenn Sie einen bestimmten Startwert angeben müssen, damit RNG dupliziert werden kann, verwenden Sie, srand(x)
wo x
sich der Startwert befindet. Aus dem numerischen Funktionshandbuch von GNU awk geht hervor, dass "verschiedene awk-Implementierungen intern unterschiedliche Zufallszahlengeneratoren verwenden". Das Ergebnis ist, dass Sie, wenn Sie an der Erstellung einer statistischen Verteilung interessiert sind, geringfügige Abweichungen von einer Laufzeit zur nächsten auf verschiedenen Plattformen (alle ausgeführt awk
oder gawk
) erwarten sollten .
Es gibt $ RANDOM. Ich weiß nicht genau, wie es funktioniert. Aber es funktioniert. Zum Testen können Sie Folgendes tun:
echo $RANDOM
Ich mag diesen Trick:
echo ${RANDOM:0:1} # random number between 1 and 9
echo ${RANDOM:0:2} # random number between 1 and 99
...
${RANDOM:0:1}
hat eine 67,8% ige Chance, Ihnen eine 1 oder 2 zu geben, hat ${RANDOM:0:2}
nur eine 0,03% ige Chance, Ihnen eine einstellige Zahl zu geben (sollte 1% sein), und beide haben eine 0,003% ige Chance, Ihnen eine 0 zu geben Es gibt immer noch Anwendungsfälle, in denen dies in Ordnung ist (z. B. nicht konsistente Eingabe).
Zufallszahl zwischen 0 und 9 einschließlich.
echo $((RANDOM%10))
$RANDOM
geht nur von 0 bis 32767. Es sollte gesagt haben "Zufallszahl meist zwischen 1 und 3, mit ein paar Flügelspielern";)
Wenn Sie ein Linux-System verwenden, können Sie eine Zufallszahl aus / dev / random oder / dev / urandom abrufen. Seien Sie vorsichtig, wenn / dev / random blockiert, wenn nicht genügend Zufallszahlen verfügbar sind. Wenn Sie Geschwindigkeit über Zufälligkeit benötigen, verwenden Sie / dev / urandom.
Diese "Dateien" werden mit Zufallszahlen gefüllt, die vom Betriebssystem generiert werden. Es hängt von der Implementierung von / dev / random auf Ihrem System ab, ob Sie echte oder Pseudozufallszahlen erhalten. Echte Zufallszahlen werden mithilfe von Rauschen generiert, das von Gerätetreibern wie Maus, Festplatte und Netzwerk erfasst wird.
Ich habe einige dieser Ideen aufgegriffen und eine Funktion entwickelt, die schnell ausgeführt werden sollte, wenn viele Zufallszahlen erforderlich sind.
Anrufen od
ist teuer, wenn Sie viele Zufallszahlen benötigen. Stattdessen rufe ich es einmal auf und speichere 1024 Zufallszahlen aus / dev / urandom. Wannrand
Aufruf wird die letzte Zufallszahl zurückgegeben und skaliert. Es wird dann aus dem Cache entfernt. Wenn der Cache leer ist, werden weitere 1024 Zufallszahlen gelesen.
Beispiel:
rand 10; echo $RET
Gibt eine Zufallszahl in RET zwischen 0 und 9 einschließlich zurück.
declare -ia RANDCACHE
declare -i RET RAWRAND=$(( (1<<32)-1 ))
function rand(){ # pick a random number from 0 to N-1. Max N is 2^32
local -i N=$1
[[ ${#RANDCACHE[*]} -eq 0 ]] && { RANDCACHE=( $(od -An -tu4 -N1024 /dev/urandom) ); } # refill cache
RET=$(( (RANDCACHE[-1]*N+1)/RAWRAND )) # pull last random number and scale
unset RANDCACHE[${#RANDCACHE[*]}-1] # pop read random number
};
# test by generating a lot of random numbers, then effectively place them in bins and count how many are in each bin.
declare -i c; declare -ia BIN
for (( c=0; c<100000; c++ )); do
rand 10
BIN[RET]+=1 # add to bin to check distribution
done
for (( c=0; c<10; c++ )); do
printf "%d %d\n" $c ${BIN[c]}
done
UPDATE: Das funktioniert nicht für alle N. Es verschwendet auch zufällige Bits, wenn es mit kleinem N verwendet wird. Beachten Sie, dass (in diesem Fall) eine 32-Bit-Zufallszahl genug Entropie für 9 Zufallszahlen zwischen 0 und 9 (10 * 9) hat = 1.000.000.000 <= 2 * 32) Wir können mehrere Zufallszahlen aus jedem 32 zufälligen Quellwert extrahieren.
#!/bin/bash
declare -ia RCACHE
declare -i RET # return value
declare -i ENT=2 # keep track of unused entropy as 2^(entropy)
declare -i RND=RANDOM%ENT # a store for unused entropy - start with 1 bit
declare -i BYTES=4 # size of unsigned random bytes returned by od
declare -i BITS=8*BYTES # size of random data returned by od in bits
declare -i CACHE=16 # number of random numbers to cache
declare -i MAX=2**BITS # quantum of entropy per cached random number
declare -i c
function rand(){ # pick a random number from 0 to 2^BITS-1
[[ ${#RCACHE[*]} -eq 0 ]] && { RCACHE=( $(od -An -tu$BYTES -N$CACHE /dev/urandom) ); } # refill cache - could use /dev/random if CACHE is small
RET=${RCACHE[-1]} # pull last random number and scale
unset RCACHE[${#RCACHE[*]}-1] # pop read random number
};
function randBetween(){
local -i N=$1
[[ ENT -lt N ]] && { # not enough entropy to supply ln(N)/ln(2) bits
rand; RND=RET # get more random bits
ENT=MAX # reset entropy
}
RET=RND%N # random number to return
RND=RND/N # remaining randomness
ENT=ENT/N # remaining entropy
};
declare -ia BIN
for (( c=0; c<100000; c++ )); do
randBetween 10
BIN[RET]+=1
done
for c in ${BIN[*]}; do
echo $c
done
od -An -tu4 -N40 /dev/urandom
generiert 10 zufällige vorzeichenlose 32-Bit-Ganzzahlen, die durch Leerzeichen getrennt sind. Sie können es in einem Array speichern und anschließend verwenden. Ihr Code scheint ein Overkill zu sein.
Das Lesen aus speziellen Dateien mit / dev / random- oder / dev / urandom-Zeichen ist der richtige Weg.
Diese Geräte geben beim Lesen wirklich zufällige Zahlen zurück und sollen der Anwendungssoftware bei der Auswahl sicherer Schlüssel für die Verschlüsselung helfen. Solche Zufallszahlen werden aus einem Entropiepool extrahiert, der durch verschiedene Zufallsereignisse bereitgestellt wird. {LDD3, Jonathan Corbet, Alessandro Rubini und Greg Kroah-Hartman]
Diese beiden Dateien sind insbesondere eine Schnittstelle zur Kernel-Randomisierung
void get_random_bytes_arch(void* buf, int nbytes)
Dies zieht wirklich zufällige Bytes von der Hardware, wenn diese Funktion von der implementierten Hardware ist (normalerweise) oder aus dem Entropiepool (bestehend aus Zeitabläufen zwischen Ereignissen wie Maus- und Tastatur-Interrupts und anderen Interrupts, die bei SA_SAMPLE_RANDOM registriert sind).
dd if=/dev/urandom count=4 bs=1 | od -t d
Dies funktioniert, schreibt jedoch nicht benötigte Ausgaben von dd
in stdout. Der folgende Befehl gibt nur die Ganzzahl an, die ich benötige. Ich kann sogar eine bestimmte Anzahl von Zufallsbits erhalten, wenn ich die Bitmaske für die arithmetische Erweiterung anpasse:
me@mymachine:~/$ x=$(head -c 1 /dev/urandom > tmp && hexdump
-d tmp | head -n 1 | cut -c13-15) && echo $(( 10#$x & 127 ))
Vielleicht bin ich etwas zu spät, aber was ist mit jot
der Generierung einer Zufallszahl innerhalb eines Bereichs in Bash?
jot -r -p 3 1 0 1
Dies erzeugt eine Zufallszahl ( -r
) mit einer Genauigkeit von 3 Dezimalstellen ( -p
). In diesem speziellen Fall erhalten Sie eine Zahl zwischen 0 und 1 ( 1 0 1
). Sie können auch sequentielle Daten drucken. Die Quelle der Zufallszahl ist laut Handbuch:
Zufallszahlen werden durch arc4random (3) erhalten, wenn kein Startwert angegeben ist, und durch Zufallszahlen (3), wenn ein Startwert angegeben wird.
Basierend auf den großartigen Antworten von @Nelson, @Barun und @Robert ist hier ein Bash-Skript, das Zufallszahlen generiert.
/dev/urandom
was viel besser ist als die von Bash integrierte$RANDOM
#!/usr/bin/env bash
digits=10
rand=$(od -A n -t d -N 2 /dev/urandom |tr -d ' ')
num=$((rand % 10))
while [ ${#num} -lt $digits ]; do
rand=$(od -A n -t d -N 1 /dev/urandom |tr -d ' ')
num="${num}$((rand % 10))"
done
echo $num
Generieren Sie eine Zufallszahl im Bereich von 0 bis n (vorzeichenbehaftete 16-Bit-Ganzzahl). Ergebnis in $ RAND Variable gesetzt. Beispielsweise:
#!/bin/bash
random()
{
local range=${1:-1}
RAND=`od -t uI -N 4 /dev/urandom | awk '{print $2}'`
let "RAND=$RAND%($range+1)"
}
n=10
while [ $(( n -=1 )) -ge "0" ]; do
random 500
echo "$RAND"
done
Zufällige Verzweigung eines Programms oder ja / nein; 1/0; wahre / falsche Ausgabe:
if [ $RANDOM -gt 16383 ]; then # 16383 = 32767/2
echo var=true/1/yes/go_hither
else
echo var=false/0/no/go_thither
fi
von wenn Sie faul sind, sich an 16383 zu erinnern:
if (( RANDOM % 2 )); then
echo "yes"
else
echo "no"
fi