Comment générer des nombres aléatoires en Bash?
13 réponses
Utilisation $RANDOM
. Il est souvent utile en combinaison avec simple arithmétique shell. Par exemple, pour générer un nombre aléatoire entre 1 et 10:
$ echo $((1 + RANDOM % 10))
3
le générateur actuel est dans variables.c
, la fonction brand()
. les anciennes versions étaient une simple génératrice linéaire. La Version 4.0 de bash
utilise un générateur avec une citation à un papier de 1985, qui probablement ça veut dire que c'est une bonne source de pseudo-nombres. Je ne l'utiliserais pas pour une simulation (et certainement pas pour la cryptographie), mais il est probablement adéquat 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
s'il vous Plaît voir $RANDOM
:
$RANDOM
est une fonction interne de Bash (pas une constante) qui renvoie un pseudo entier dans la gamme 0 - 32767. Il ne devrait pas être utilisé pour générer une clé de chiffrement.
Essayez ce à partir de 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 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 il fonctionne. Mais il fonctionne. Pour les tests, vous pouvez faire:
echo $RANDOM
vous pouvez également utiliser shuf (disponible en coreutils).
shuf -i 1-100000 -n 1
nombre aléatoire entre 0 et 9 inclusivement.
echo $((RANDOM%10))
Si vous utilisez un système linux, vous pouvez obtenir un nombre aléatoire de /dev/random ou /dev/urandom. Be carefull / dev / random bloquera s'il n'y a pas assez de nombres aléatoires disponibles. Si vous avez besoin de vitesse sur randomness utiliser /dev/urandom.
ces" fichiers " seront remplis de 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 aléatoires vrais ou pseudo. Vrai des nombres aléatoires sont générés avec l'aide du bruit de forme recueilli de pilotes de périphérique comme la souris, le disque dur, le réseau.
vous pouvez obtenir des nombres aléatoires à partir du fichier avec dd
j'ai pris quelques-unes de ces idées et fait une fonction qui devrait fonctionner rapidement si beaucoup de nombres aléatoires sont nécessaires.
appel od
est cher 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 de /dev/urandom. Lorsque rand
est appelé, le dernier nombre aléatoire est retourné et mis à l'échelle. Il est ensuite retiré du cache. Lorsque le cache est vide, un autre 1024 nombres aléatoires est lu.
Exemple:
rand 10; echo $RET
renvoie un nombre aléatoire dans RET entre 0 et 9 inclusivement.
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=
[[ ${#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
mise à jour: cela ne fonctionne pas si bien pour tous les N. il gaspille aussi des bits aléatoires si utilisé avec de petits N. notant que (dans ce cas) un nombre aléatoire de 32 bits a assez d'entropie pour 9 nombres aléatoires entre 0 et 9 (10* 9=1,000,000,000 <= 2 *32) nous pouvons extraire plusieurs nombres aléatoires de chaque valeur de 32 sources aléatoires.
#!/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=
[[ 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 lecture des fichiers spéciaux de caractères /dev/random ou /dev/urandom est la voie à suivre.
ces appareils renvoient des nombres vraiment aléatoires lorsqu'ils sont lus et sont conçus pour aider les logiciels d'application à choisir des clés de cryptage sécurisées. Tel les nombres aléatoires sont extraits d'un pool d'entropie qui est fourni par divers événements aléatoires. {LDD3, Jonathan Corbet, Alessandro Rubini, and Greg Kroah-Hartman]
ces deux fichiers sont l'interface pour la randomisation du noyau, en particulier
void get_random_bytes_arch(void* buf, int nbytes)
qui tire vraiment des octets aléatoires du matériel si une telle fonction est par matériel implémenté (est généralement), ou il tire de Entropy pool (composé de minuteries entre des événements comme les interruptions de souris et de clavier et d'autres interruptions qui sont enregistrés avec SA_SAMPLE_RANDOM).
dd if=/dev/urandom count=4 bs=1 | od -t d
cela fonctionne, mais écrit la sortie inutile de dd
à stdout. Commande ci-dessous donne juste l'entier dont j'ai besoin. Je peux même obtenir le nombre spécifié de bits aléatoires comme j'ai besoin en ajustant le bitmask donné à l'expansion 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'aime cette astuce:
echo ${RANDOM:0:1} # random number between 1 and 9
echo ${RANDOM:0:2} # random number between 1 and 99
...
génère un nombre aléatoire dans l'intervalle de 0 à n (entier 16 bits signé). 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 }'`
let "RAND=$RAND%($range+1)"
}
n=10
while [ $(( n -=1 )) -ge "0" ]; do
random 500
echo "$RAND"
done