¿Cómo generar un número aleatorio en Bash?

¿Cómo generar un número aleatorio dentro de un rango en Bash?

Usa $RANDOM . A menudo es útil en combinación con la simple aritmética de shell. Por ejemplo, para generar un número aleatorio entre 1 y 10:

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

El generador real está en variables.c , la función de brand() . Las versiones anteriores eran un generador lineal simple. La versión 4.0 de bash usa un generador con una cita de un documento de 1985, lo que presumiblemente significa que es una fuente decente de números pseudoaleatorios. No lo usaría para una simulación (y ciertamente no para criptografía), pero probablemente sea adecuado para tareas básicas de scripting.

Si estás haciendo algo que requiere números aleatorios serios, puedes usar /dev/random o /dev/urandom si están disponibles:

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

Por favor, vea $RANDOM :

$RANDOM es una función Bash interna (no una constante) que devuelve un entero pseudoaleatorio en el rango 0 – 32767. No debe usarse para generar una clave de cifrado.

Prueba esto desde tu caparazón:

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

Aquí, -td especifica que el formato de salida debe ser un decimal firmado; -N 1 dice leer un byte de /dev/urandom .

también puedes obtener un número aleatorio de awk

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

Hay $ RANDOM. No sé exactamente cómo funciona. Pero funciona. Para la prueba, puede hacer:

 echo $RANDOM 

También puedes usar shuf (disponible en coreutils).

 shuf -i 1-100000 -n 1 

Número aleatorio entre 0 y 9 inclusive.

 echo $((RANDOM%10)) 

Si está utilizando un sistema Linux, puede obtener un número aleatorio de / dev / random o / dev / urandom. Tenga cuidado / dev / random bloqueará si no hay suficientes números aleatorios disponibles. Si necesita velocidad sobre la aleatoriedad, use / dev / urandom.

Estos “archivos” se llenarán con números aleatorios generados por el sistema operativo. Depende de la implementación de / dev / random en su sistema si obtiene números verdaderos o pseudoaleatorios. Los verdaderos números aleatorios se generan con la ayuda del ruido generado por los controladores del dispositivo, como el mouse, el disco duro o la red.

Puedes obtener números aleatorios del archivo con dd

Tomé algunas de estas ideas e hice una función que debería funcionar rápidamente si se requieren muchos números aleatorios.

Llamar a od es costoso si necesita muchos números aleatorios. En cambio, lo llamo una vez y almaceno 1024 números aleatorios de / dev / urandom. Cuando se llama rand , se devuelve y escala el último número aleatorio. Luego se elimina de la memoria caché. Cuando la memoria caché está vacía, se leen otros 1024 números aleatorios.

Ejemplo:

 rand 10; echo $RET 

Devuelve un número aleatorio en RET entre 0 y 9 inclusive.

 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 

ACTUALIZACIÓN: Eso no funciona tan bien para todos N. También desperdicia bits aleatorios si se usa con N pequeña. Teniendo en cuenta que (en este caso) un número aleatorio de 32 bits tiene suficiente entropía para 9 números aleatorios entre 0 y 9 (10 * 9 = 1,000,000,000 <= 2 * 32) podemos extraer múltiples números aleatorios de cada 32 valores fuente aleatorios.

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

Leer archivos especiales de / dev / random o / dev / urandom es el camino a seguir.

Estos dispositivos devuelven números verdaderamente aleatorios cuando se leen y están diseñados para ayudar al software de la aplicación a elegir claves seguras para el cifrado. Dichos números aleatorios se extraen de un conjunto de entropía aportado por varios eventos aleatorios. {LDD3, Jonathan Corbet, Alessandro Rubini y Greg Kroah-Hartman]

Estos dos archivos son interfaz para la aleatorización del núcleo, en particular

 void get_random_bytes_arch(void* buf, int nbytes) 

que extrae bytes verdaderamente aleatorios del hardware si dicha función es implementada por hardware (normalmente lo es), o se basa en un conjunto de entropía (compuesto por temporizaciones entre eventos como interrupciones de mouse y teclado y otras interrupciones registradas con SA_SAMPLE_RANDOM).

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

Esto funciona, pero escribe resultados innecesarios de dd a stdout. El siguiente comando da solo el entero que necesito. Incluso puedo obtener el número especificado de bits aleatorios que necesito ajustando la máscara de bits dada a la expansión aritmética:

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

Me gusta este truco:

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

Genere un número aleatorio en el rango de 0 a n (entero de 16 bits con signo). Resultado establecido en la variable $ RAND. Por ejemplo:

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

Qué pasa:

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