Utilisez $RANDOM. Il est souvent utile en combinaison avec une simple arithmétique de coque. Par exemple, pour générer un nombre aléatoire entre 1 et 10 (inclus):
$ echo $((1+ RANDOM %10))3
Le générateur réel est dans variables.cla fonction brand(). Les anciennes versions étaient un simple générateur linéaire. La version 4.0 bashutilise un générateur avec une citation d'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 les utiliser /dev/randomou /dev/urandoms'ils sont disponibles:
Faites attention ici. Bien que cela soit bien dans un pincement, faire de l'arithmétique sur des nombres aléatoires peut considérablement affecter le caractère aléatoire de votre résultat. dans le cas de $RANDOM % 10, 8 et 9 sont mesurables (bien que marginalement) moins probables que 0-7, même s'il $RANDOMs'agit d'une source robuste de données aléatoires.
dimo414
3
@ dimo414 Je suis curieux de "marginalement", avez-vous une source où je peux en savoir plus à ce sujet?
PascalVKooten
58
En modulant vos entrées aléatoires, vous « collez » les résultats. Puisque $RANDOMla plage est constituée de 0-32767nombres 0- 7mappez sur 3277différentes entrées possibles, mais 8et 9ne pouvez être produites que de 3276différentes manières (car 32768et 32769ne sont pas possibles). Il s'agit d'un problème mineur pour les hacks rapides, mais cela signifie que le résultat n'est pas uniformément aléatoire. Les bibliothèques aléatoires, comme Java Random, offrent des fonctions pour renvoyer correctement un nombre aléatoire uniforme dans la plage donnée, plutôt que de simplement modifier un nombre non divisible.
dimo414
1
@JFSebastian très vrai - le problème avec modulo est qu'il peut casser l'uniformité de n'importe quel RNG, pas seulement de mauvais PRNG, mais merci de l'avoir appelé.
dimo414
14
Juste pour le contexte, le pigeonholing de base pour% 10 signifie que 8 et 9 sont environ 0,03% moins susceptibles de se produire que 0–7. Si votre script shell nécessite des nombres aléatoires uniformes plus précis que cela, alors utilisez certainement un mécanisme plus complexe et approprié.
$RANDOM est une fonction Bash interne (pas une constante) qui renvoie un entier pseudo-aléatoire dans la plage 0 - 32767. Elle ne doit pas être utilisée pour générer une clé de chiffrement.
@JinKwon 32767est 2^16 / 2 - 1la limite supérieure d'un entier signé de 16 bits.
Jeffrey Martinez
@JinKwon pourriez-vous clarifier pourquoi ne dites-vous pas que c'est le cas 2^15 - 1? C'est équivalent, donc je suis juste curieux de savoir s'il y a un contexte qui me manque?
Brett Holman
11
@BrettHolman Je pense qu'il essayait de souligner la partie "signée" de l'entier 16 bits signé. 2 ^ 16 valeurs, divisées en deux pour les entiers positifs et négatifs.
cody
Cette réponse ne répond pas à la question.
morveux
48
Vous pouvez également utiliser shuf (disponible dans coreutils).
Comment passez-vous en vars en fin de gamme? J'ai eu ceci:shuf -i 1-10 -n 1: syntax error in expression (error token is "1-10 -n 1")
dat tutbrus
1
Ajoutez un $varau lieu de la fin de la plage, comme ceci:var=100 && shuf -i 1-${var} -n 1
knipwim
2
Je préfère cette option car il est facile de générer N nombres aléatoires avec -n. Par exemple, générer 5 nombres aléatoires entre 1 et 100 :shuf -i 1-100 -n 5
aerijman
Autant que je sache, les chiffres ne sont pas aléatoires. Si vous spécifiez, shuf -i 1-10 -n 10vous obtiendrez tous les nombres de 1 à 10 exactement. Si vous spécifiez, -n 15vous n'obtiendrez toujours qu'une seule fois ces 10 numéros. Ce n'est que du brassage, pas de génération de nombres aléatoires.
radlan le
Pour obtenir des nombres aléatoires avec remplacement: -r
Geoffrey Anderson
36
Essayez ceci depuis votre shell:
$ od -A n -t d -N 1/dev/urandom
Ici, -t dspécifie que le format de sortie doit être signé décimal; -N 1dit de lire un octet de /dev/urandom.
+1 vous savez, au début, je me demandais pourquoi voudriez-vous jamais le faire comme ça, mais en fait je l'aime bien.
zelanix
1
Merci d'avoir donné une solution qui inclut l'ensemencement. Je ne l'ai trouvé nulle part!
so.very.tired
2
+1 pour l'ensemencement. Il peut être utile de mentionner que srand()le germe est le temps CPU actuel. Si vous devez spécifier une graine spécifique, afin que RNG puisse être dupliqué, utilisez srand(x)où xest la graine. Également, cité dans le manuel des fonctions numériques de GNU awk, «différentes implémentations awk utilisent différents générateurs de nombres aléatoires en interne». Le résultat est que si vous souhaitez générer une distribution statistique, vous devez vous attendre à de légères variations allant d'un runtime à l'autre sur une plateforme différente (toutes en cours d'exécution awkou gawk).
Cbhihe
18
Il y a $ RANDOM. Je ne sais pas exactement comment ça marche. Mais ça marche. Pour les tests, vous pouvez faire:
$ RANDOM est compris entre 0 et 32 767. Vous obtiendrez plus de nombres commençant par 1, 2 ou 3 que vous n'en avez 4-9. Si vous êtes d'accord avec une distribution déséquilibrée, cela fonctionnera bien.
jbo5112
2
@ jbo5112 vous avez tout à fait raison, qu'en est-il de l'affichage du dernier chiffre? echo $ {RANDOM: 0-1} pour un chiffre, $ {RANDOM: 0-2} pour deux chiffres ...?
fraff
4
Si vous utilisez le (s) dernier (s) chiffre (s), ce sera plutôt bien, mais il inclura des 0 et des 00. Sur un seul chiffre, 0-7 se produira 0,03% plus souvent que 8-9. Sur 2 chiffres, 0-67 se produira 0,3% plus souvent que 68-99. Si vous avez besoin d'une distribution de nombres aléatoires aussi bonne, j'espère que vous n'utilisez pas bash. Avec l'original: ${RANDOM:0:1}a 67,8% de chances de vous donner un 1 ou un 2, ${RANDOM:0:2}n'a que 0,03% de chances de vous donner un numéro à un chiffre (devrait être de 1%), et les deux ont 0,003% de chances de vous donner un 0 Il existe encore des cas d'utilisation où cela est correct (par exemple, entrée non cohérente).
Mon mauvais, n'a pas lu la page de manuel correctement. $RANDOMne va que de 0 à 32767. Il aurait dû dire "Nombre aléatoire principalement entre 1 et 3, avec quelques ailiers";)
David Newcomb
1
Quoi? Ce sera toujours entre 0 et 9, bien que 8 et 9 auront une probabilité légèrement inférieure de se produire de 0 à 7, comme mentionné dans une autre réponse.
kini
6
Si vous utilisez un système Linux, vous pouvez obtenir un nombre aléatoire dans / dev / random ou / dev / urandom. Attention, dev / random bloquera s'il n'y a pas assez de nombres aléatoires disponibles. Si vous avez besoin de vitesse par rapport à l'aléatoire, utilisez / 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 vrais ou pseudo aléatoires. De vrais nombres aléatoires sont générés avec l'aide du bruit provenant des pilotes de périphériques 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 créé une fonction qui devrait fonctionner rapidement si de nombreux nombres aléatoires sont nécessaires.
appeler odcoûte cher si vous avez besoin de beaucoup de numéros aléatoires. Au lieu de cela, je l'appelle une fois et stocke 1024 numéros aléatoires à partir de / dev / urandom. Lorsque randest appelé, le dernier nombre aléatoire est renvoyé et mis à l'échelle. Il est ensuite supprimé du cache. Lorsque le cache est vide, 1024 autres nombres aléatoires sont lus.
Exemple:
rand 10; echo $RET
Renvoie 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^32local-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 distributiondonefor(( 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 également des bits aléatoires s'il est utilisé avec de petits N. Notant que (dans ce cas) un nombre aléatoire de 32 bits a suffisamment 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 32 valeur source 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]+=1donefor c in ${BIN[*]};do
echo $c
done
J'ai essayé cela - cela a pris 10 secondes de 100% cpu, puis j'ai imprimé 10 chiffres qui ne semblaient pas aléatoires.
Carlo Wood
Je me souviens maintenant. Ce code génère 100 000 nombres aléatoires. Il place chacun dans un «bac» pour voir à quel point il est aléatoire. Il y a 10 bacs. Ces nombres devraient être similaires si chaque nombre aléatoire entre 0 et 9 est également probable. Si vous souhaitez imprimer chaque numéro, faites écho à $ RET après randBetween 10.
philcolbourn
od -An -tu4 -N40 /dev/urandomgénérera 10 entiers aléatoires non signés de 32 bits séparés par des espaces. vous pouvez le stocker dans un tableau et l'utiliser ensuite. votre code semble exagéré.
Ali
@Ali, OP n'a pas précisé qu'il voulait 32 bits ni aucun autre nombre aléatoire de taille. Moi et d'autres avons interprété cette question comme fournissant un nombre aléatoire dans une plage. Ma fonction rand atteint cet objectif et réduit également la perte d'entropie qui, si elle est épuisée, bloque les programmes. od on / dev / urandom ne renvoie que des nombres aléatoires de 2 ^ N bits et OP devrait alors stocker plusieurs valeurs dans un tableau, les extraire séquentiellement de ce tableau et reconstituer ce tableau. Peut-être pouvez-vous coder cela comme une réponse et gérer d'autres plages de nombres aléatoires?
philcolbourn
@philcolbourn, vous avez raison au sujet de l'OP ne spécifiant pas quel type de nombre aléatoire il veut et cela a manqué mon attention. Mais il a seulement demandé: "Comment générer un nombre aléatoire en bash?". Mon point est qu'il n'a demandé qu'un seul nombre aléatoire. Bien que cette critique s'applique également à mon commentaire précédent (générant 10 nombres aléatoires).
Ali
5
La lecture à partir de 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 sécurisées pour le chiffrement. Ces nombres aléatoires sont extraits d'un pool d'entropie alimenté 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 vraiment aléatoires du matériel si une telle fonction est implémentée par le matériel (généralement), ou il tire du pool d'entropie (composé de temporisations entre les événements comme les 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 la sortie inutile de ddà stdout. La commande ci-dessous donne juste l'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 de bits donné à l'expansion arithmétique:
Pour un nombre aléatoire cryptographiquement sécurisé, vous devez lire à partir de / dev / urandom ou utiliser les bibliothèques Crypt :: Random.
kh
3
Je suis peut-être un peu trop tard, mais qu'en est-il de l'utilisation jotpour générer un nombre aléatoire dans une plage dans Bash?
jot -r -p 3101
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 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 via arc4random (3) lorsqu'aucune graine n'est spécifiée, et via random (3) lorsqu'une graine est donnée.
Réponses:
Utilisez
$RANDOM
. Il est souvent utile en combinaison avec une simple arithmétique de coque. Par exemple, pour générer un nombre aléatoire entre 1 et 10 (inclus):Le générateur réel est dans
variables.c
la fonctionbrand()
. Les anciennes versions étaient un simple générateur linéaire. La version 4.0bash
utilise un générateur avec une citation d'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 les utiliser
/dev/random
ou/dev/urandom
s'ils sont disponibles:la source
$RANDOM % 10
, 8 et 9 sont mesurables (bien que marginalement) moins probables que 0-7, même s'il$RANDOM
s'agit d'une source robuste de données aléatoires.$RANDOM
la plage est constituée de0-32767
nombres0
-7
mappez sur3277
différentes entrées possibles, mais8
et9
ne pouvez être produites que de3276
différentes manières (car32768
et32769
ne sont pas possibles). Il s'agit d'un problème mineur pour les hacks rapides, mais cela signifie que le résultat n'est pas uniformément aléatoire. Les bibliothèques aléatoires, comme JavaRandom
, offrent des fonctions pour renvoyer correctement un nombre aléatoire uniforme dans la plage donnée, plutôt que de simplement modifier un nombre non divisible.Veuillez voir
$RANDOM
:la source
32767
une signification particulière?32767
est2^16 / 2 - 1
la limite supérieure d'un entier signé de 16 bits.2^15 - 1
? C'est équivalent, donc je suis juste curieux de savoir s'il y a un contexte qui me manque?Vous pouvez également utiliser shuf (disponible dans coreutils).
la source
shuf -i 1-10 -n 1: syntax error in expression (error token is "1-10 -n 1")
$var
au lieu de la fin de la plage, comme ceci:var=100 && shuf -i 1-${var} -n 1
-n
. Par exemple, générer 5 nombres aléatoires entre 1 et 100 :shuf -i 1-100 -n 5
shuf -i 1-10 -n 10
vous obtiendrez tous les nombres de 1 à 10 exactement. Si vous spécifiez,-n 15
vous n'obtiendrez toujours qu'une seule fois ces 10 numéros. Ce n'est que du brassage, pas de génération de nombres aléatoires.Essayez ceci depuis votre shell:
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
.la source
od -A n -t d -N 1 /dev/urandom |tr -d ' '
vous pouvez également obtenir un nombre aléatoire de awk
la source
srand()
le germe est le temps CPU actuel. Si vous devez spécifier une graine spécifique, afin que RNG puisse être dupliqué, utilisezsrand(x)
oùx
est la graine. Également, cité dans le manuel des fonctions numériques de GNU awk, «différentes implémentations awk utilisent différents générateurs de nombres aléatoires en interne». Le résultat est que si vous souhaitez générer une distribution statistique, vous devez vous attendre à de légères variations allant d'un runtime à l'autre sur une plateforme différente (toutes en cours d'exécutionawk
ougawk
).Il y a $ RANDOM. Je ne sais pas exactement comment ça marche. Mais ça marche. Pour les tests, vous pouvez faire:
la source
J'aime cette astuce:
...
la source
${RANDOM:0:1}
a 67,8% de chances de vous donner un 1 ou un 2,${RANDOM:0:2}
n'a que 0,03% de chances de vous donner un numéro à un chiffre (devrait être de 1%), et les deux ont 0,003% de chances de vous donner un 0 Il existe encore des cas d'utilisation où cela est correct (par exemple, entrée non cohérente).Nombre aléatoire entre 0 et 9 inclus.
la source
$RANDOM
ne va que de 0 à 32767. Il aurait dû dire "Nombre aléatoire principalement entre 1 et 3, avec quelques ailiers";)Si vous utilisez un système Linux, vous pouvez obtenir un nombre aléatoire dans / dev / random ou / dev / urandom. Attention, dev / random bloquera s'il n'y a pas assez de nombres aléatoires disponibles. Si vous avez besoin de vitesse par rapport à l'aléatoire, utilisez / 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 vrais ou pseudo aléatoires. De vrais nombres aléatoires sont générés avec l'aide du bruit provenant des pilotes de périphériques comme la souris, le disque dur, le réseau.
Vous pouvez obtenir des nombres aléatoires à partir du fichier avec dd
la source
J'ai pris quelques-unes de ces idées et créé une fonction qui devrait fonctionner rapidement si de nombreux nombres aléatoires sont nécessaires.
appeler
od
coûte cher si vous avez besoin de beaucoup de numéros aléatoires. Au lieu de cela, je l'appelle une fois et stocke 1024 numéros aléatoires à partir de / dev / urandom. Lorsquerand
est appelé, le dernier nombre aléatoire est renvoyé et mis à l'échelle. Il est ensuite supprimé du cache. Lorsque le cache est vide, 1024 autres nombres aléatoires sont lus.Exemple:
Renvoie un nombre aléatoire dans RET compris entre 0 et 9 inclus.
MISE À JOUR: Cela ne fonctionne pas si bien pour tous les N. Il gaspille également des bits aléatoires s'il est utilisé avec de petits N. Notant que (dans ce cas) un nombre aléatoire de 32 bits a suffisamment 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 32 valeur source aléatoire.
la source
od -An -tu4 -N40 /dev/urandom
générera 10 entiers aléatoires non signés de 32 bits séparés par des espaces. vous pouvez le stocker dans un tableau et l'utiliser ensuite. votre code semble exagéré.La lecture à partir de fichiers spéciaux de caractères / dev / random ou / dev / urandom est la voie à suivre.
Ces deux fichiers sont une interface pour la randomisation du noyau, en particulier
qui tire des octets vraiment aléatoires du matériel si une telle fonction est implémentée par le matériel (généralement), ou il tire du pool d'entropie (composé de temporisations entre les événements comme les interruptions de souris et de clavier et d'autres interruptions enregistrées avec SA_SAMPLE_RANDOM).
Cela fonctionne, mais écrit la sortie inutile de
dd
à stdout. La commande ci-dessous donne juste l'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 de bits donné à l'expansion arithmétique:la source
Qu'en est-il de:
la source
Je suis peut-être un peu trop tard, mais qu'en est-il de l'utilisation
jot
pour générer un nombre aléatoire dans une plage dans Bash?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 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:la source
Basé sur les bonnes réponses de @Nelson, @Barun et @Robert, voici un script Bash qui génère des nombres aléatoires.
/dev/urandom
ce qui est bien meilleur que le Bash intégré$RANDOM
la source
Générez un nombre aléatoire dans la plage de 0 à n (entier 16 bits signé). Jeu de résultats dans la variable $ RAND. Par exemple:
la source
Branchement aléatoire d'un programme ou oui / non; 1/0; sortie vrai / faux:
de si vous paresseux de vous rappeler 16383:
la source