Comment générer un nombre aléatoire dans une plage dans Bash?
Utilisez $RANDOM
. C'est souvent utile en combinaison avec l'arithmétique simple de Shell. Par exemple, pour générer un nombre aléatoire compris entre 1 et 10:
_$ echo $((1 + RANDOM % 10))
3
_
Le générateur actuel est en _variables.c
_, la fonction brand()
. Anciennes versions étaient un simple générateur linéaire. La version 4.0 de bash
utilise un générateur avec une citation à un article de 1985, ce qui signifie probablement que c'est une source décente de nombres pseudo-aléatoires. Je ne l'utiliserais pas pour une simulation (et certainement pas pour la cryptographie), mais c'est probablement suffisant pour les tâches de script de base.
Si vous faites quelque chose qui nécessite des nombres aléatoires sérieux, vous pouvez utiliser _/dev/random
_ ou _/dev/urandom
_ s'ils sont disponibles:
_$ dd if=/dev/urandom count=4 bs=1 | od -t d
_
Veuillez voir $RANDOM
:
_
$RANDOM
_ est une fonction Bash interne (et non une constante) qui renvoie un entier pseudo-aléatoire compris entre 0 et 32767. Elle ne doit pas être utilisée pour générer une clé de cryptage.
Essayez ceci depuis votre shell:
$ od -A n -t d -N 1 /dev/urandom
Ici, -t d
spécifie que le format de sortie doit être signé décimal; -N 1
dit de lire un octet de /dev/urandom
.
Vous pouvez également utiliser shuf (disponible dans les coreutils).
shuf -i 1-100000 -n 1
vous pouvez également obtenir un nombre aléatoire de awk
awk 'BEGIN {
# seed
srand()
for (i=1;i<=1000;i++){
print int(1 + Rand() * 100)
}
}'
Il y a $ RANDOM. Je ne sais pas exactement comment ça marche. Mais ça marche. Pour tester, vous pouvez faire:
echo $RANDOM
Nombre aléatoire compris entre 0 et 9 inclus.
echo $((RANDOM%10))
J'aime cette astuce:
echo ${RANDOM:0:1} # random number between 1 and 9
echo ${RANDOM:0:2} # random number between 1 and 99
...
Si vous utilisez un système Linux, vous pouvez obtenir un nombre aléatoire parmi / dev/random o /dev/urandom. Attention, dev/random bloquera s'il n'y a pas assez de nombres aléatoires disponibles. Si vous avez besoin de vitesse plutôt que d’aléatoire, utilisez/dev/urandom.
Ces "fichiers" seront remplis avec des nombres aléatoires générés par le système d'exploitation. Cela dépend de l'implémentation de/dev/random sur votre système si vous obtenez des nombres vrais ou pseudo aléatoires. Les vrais nombres aléatoires sont générés avec l'aide du bruit provenant des pilotes de périphérique tels que souris, disque dur, réseau.
Vous pouvez obtenir des nombres aléatoires à partir du fichier avec dd
Lire des fichiers spéciaux de caractères/dev/random ou/dev/urandom est la voie à suivre.
Ces périphériques renvoient des nombres réellement aléatoires lors de la lecture et sont conçus pour aider les applications à choisir des clés sécurisées pour le cryptage. Ces nombres aléatoires sont extraits d'un pool d'entropie généré par divers événements aléatoires. {LDD3, Jonathan Corbet, Alessandro Rubini et Greg Kroah-Hartman]
Ces deux fichiers sont une interface pour la randomisation du noyau, en particulier
void get_random_bytes_Arch(void* buf, int nbytes)
qui tire des octets véritablement aléatoires du matériel si cette fonction est implémentée par le matériel (généralement), ou du pool d'entropie (composé de minutages entre des événements tels que des interruptions de souris et de clavier et d'autres interruptions enregistrées avec SA_SAMPLE_RANDOM).
dd if=/dev/urandom count=4 bs=1 | od -t d
Cela fonctionne, mais écrit les sorties inutiles de dd
sur stdout. La commande ci-dessous donne juste le nombre entier dont j'ai besoin. Je peux même obtenir le nombre spécifié de bits aléatoires dont j'ai besoin en ajustant le masque binaire donné au développement arithmétique:
me@mymachine:~/$ x=$(head -c 1 /dev/urandom > tmp && hexdump
-d tmp | head -n 1 | cut -c13-15) && echo $(( 10#$x & 127 ))
J'ai repris quelques-unes de ces idées et créé une fonction qui devrait fonctionner rapidement si de nombreux nombres aléatoires sont requis.
appeler od
est coûteux si vous avez besoin de beaucoup de nombres aléatoires. Au lieu de cela, je l’appelle une fois et stocke 1024 nombres aléatoires dans/dev/urandom. Lorsque vous appelez Rand
, le dernier nombre aléatoire est renvoyé et mis à l'échelle. Il est ensuite retiré du cache. Lorsque le cache est vide, 1024 autres nombres aléatoires sont lus.
Exemple:
Rand 10; echo $RET
Retourne un nombre aléatoire dans RET compris entre 0 et 9 inclus.
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: Cela ne fonctionne pas très bien pour tous les N. Il gaspille également des bits aléatoires s’il est utilisé avec un petit N. Notant que (dans ce cas) un nombre aléatoire de 32 bits a assez d’entropie pour 9 nombres aléatoires compris entre 0 et 9 (10 * - 9 = 1 000 000 000 <= 2 * 32) nous pouvons extraire plusieurs nombres aléatoires de chaque valeur source 32 aléatoire.
#!/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
Qu'en est-il de:
Perl -e 'print int Rand 10, "\n"; '
Peut-être suis-je un peu en retard, mais qu'en est-il de l'utilisation de jot
pour générer un nombre aléatoire dans une plage de Bash?
jot -r -p 3 1 0 1
Cela génère un nombre aléatoire (-r
) avec une précision de 3 décimales (-p
). Dans ce cas particulier, vous obtiendrez un nombre compris entre 0 et 1 (1 0 1
). Vous pouvez également imprimer des données séquentielles. La source du nombre aléatoire, selon le manuel, est:
Les nombres aléatoires sont obtenus par arc4random (3) lorsqu'aucune graine n'est spécifiée, et par aléatoire (3) lorsqu'une graine est donnée.
Générez un nombre aléatoire compris entre 0 et n (entier signé de 16 bits). Résultat défini dans la variable $ Rand. Par exemple:
#!/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