Come generare un numero casuale in Bash?

Come generare un numero casuale all’interno di un intervallo in Bash?

Usa $RANDOM . È spesso utile in combinazione con l’aritmetica semplice della shell. Ad esempio, per generare un numero casuale compreso tra 1 e 10:

 $ echo $((1 + RANDOM % 10)) 3 

Il generatore attuale è in variables.c , la funzione brand() . Le versioni precedenti erano un semplice generatore lineare. La versione 4.0 di bash usa un generatore con una citazione per un articolo del 1985, che presumibilmente significa che è una fonte decente di numeri pseudocasuali. Non lo userei per una simulazione (e certamente non per crypto), ma è probabilmente adeguato per le attività di scripting di base.

Se stai facendo qualcosa che richiede numeri casuali gravi puoi usare /dev/random o /dev/urandom se sono disponibili:

 $ dd if=/dev/urandom count=4 bs=1 | od -td 

Si prega di vedere $RANDOM :

$RANDOM è una funzione di Bash interna (non una costante) che restituisce un intero pseudocasuale nell’intervallo 0 – 32767. Non deve essere utilizzato per generare una chiave di crittografia.

Prova questo dal tuo guscio:

 $ od -A n -td -N 1 /dev/urandom 

Qui, -td specifica che il formato di output deve essere firmato come decimale; -N 1 dice di leggere un byte da /dev/urandom .

puoi anche ottenere il numero casuale da awk

 awk 'BEGIN { # seed srand() for (i=1;i<=1000;i++){ print int(1 + rand() * 100) } }' 

C’è $ RANDOM. Non so esattamente come funziona. Ma funziona. Per i test, puoi fare:

 echo $RANDOM 

Puoi anche usare shuf (disponibile in coreutils).

 shuf -i 1-100000 -n 1 

Numero casuale compreso tra 0 e 9 inclusi.

 echo $((RANDOM%10)) 

Se stai usando un sistema linux puoi ottenere un numero casuale da / dev / random o / dev / urandom. Stai attento / dev / random bloccherà se non ci sono abbastanza numeri casuali disponibili. Se hai bisogno di velocità sulla casualità usa / dev / urandom.

Questi “file” saranno riempiti con numeri casuali generati dal sistema operativo. Dipende dall’implementazione di / dev / random sul tuo sistema se ottieni numeri veri o pseudo casuali. I veri numeri casuali vengono generati con il supporto del rumore raccolto dai driver di dispositivo come mouse, disco rigido, rete.

È ansible ottenere numeri casuali dal file con dd

Ho preso alcune di queste idee e ho fatto una funzione che dovrebbe funzionare rapidamente se sono richiesti molti numeri casuali.

chiamare od è costoso se hai bisogno di molti numeri casuali. Invece lo chiamo una volta e memorizzo 1024 numeri casuali da / dev / urandom. Quando viene chiamato rand , viene restituito e ridimensionato l’ultimo numero casuale. Viene quindi rimosso dalla cache. Quando la cache è vuota, vengono letti altri 1024 numeri casuali.

Esempio:

 rand 10; echo $RET 

Restituisce un numero casuale in RET tra 0 e 9 inclusi.

 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 -ic; 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 

AGGIORNAMENTO: Non funziona così bene per tutti N. Spreca anche bit casuali se usato con piccoli N. Notando che (in questo caso) un numero casuale a 32 bit ha abbastanza entropia per 9 numeri casuali tra 0 e 9 (10 * 9 = 1.000.000.000 <= 2 * 32) possiamo estrarre più numeri casuali da ogni 32 valori di origine casuale.

 #!/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 -ic 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 

La lettura dei file speciali di / dev / random o / dev / urandom è la strada da percorrere.

Questi dispositivi restituiscono numeri veramente casuali quando letti e progettati per aiutare il software applicativo a scegliere chiavi sicure per la crittografia. Tali numeri casuali vengono estratti da un pool di entropia che viene fornito da vari eventi casuali. {LDD3, Jonathan Corbet, Alessandro Rubini e Greg Kroah-Hartman]

Questi due file sono in particolare l’interfaccia con la randomizzazione del kernel

 void get_random_bytes_arch(void* buf, int nbytes) 

che disegna byte veramente casuali dall’hardware se tale funzione è implementata dall’hardware (di solito lo è), o attinge dal pool di entropia (composto da temporizzazioni tra eventi come interruzioni di mouse e tastiera e altri interrupt registrati con SA_SAMPLE_RANDOM).

 dd if=/dev/urandom count=4 bs=1 | od -td 

Funziona, ma scrive output non necessari da dd a stdout. Il comando seguente fornisce solo il numero intero di cui ho bisogno. Posso anche ottenere il numero specificato di bit casuali di cui ho bisogno regolando la maschera di bit fornita all’espansione aritmetica:

 [email protected]:~/$ x=$(head -c 1 /dev/urandom > tmp && hexdump -d tmp | head -n 1 | cut -c13-15) && echo $(( 10#$x & 127 )) 

Mi piace questo trucco:

 echo ${RANDOM:0:1} # random number between 1 and 9 echo ${RANDOM:0:2} # random number between 1 and 99 

Genera numeri casuali nell’intervallo da 0 a n (numero intero a 16 bit con segno). Risultato impostato nella variabile $ RAND. Per esempio:

 #!/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 

Che dire:

 perl -e 'print int rand 10, "\n"; '