$RANDOM est une fonction interne Bash (pas une constante) renvoyant un entier pseudo aléatoire dans l'intervalle 0 - 32767. $RANDOM ne devrait pas être utilisé pour générer une clé de cryptage.
Exemple 9-23. Générer des nombres aléatoires
#!/bin/bash # $RANDOM renvoie un entier différent à chaque invocation. # Echelle: 0 - 32767 (entier signé sur 16 bits). NBMAX=10 index=1 echo echo "$NBMAX nombres aléatoires:" echo "-----------------" while [ "$index" -le $NBMAX ] # Génère 10 ($NBMAX) entiers aléatoires. do nombre=$RANDOM echo $nombre let "index += 1" # Increment index. done echo "-----------------" # Si vous avez besoin d'un entier aléatoire dans une certaine échelle, utilisez #+ l'opérateur 'modulo'. # Il renvoie le reste d'une division. ECHELLE=500 echo nombre=$RANDOM let "nombre %= $ECHELLE" echo "Nombre aléatoire inférieur à $ECHELLE --- $nombre" echo # Si vous avez besoin d'un entier aléatoire supérieur à une borne, alors # faites un test pour annuler tous les nombres en dessous de cette borne. PLANCHER=200 nombre=0 #initialise while [ "$nombre" -le $PLANCHER ] do nombre=$RANDOM done echo "Nombre aléatoire supérieur à $PLANCHER --- $nombre" echo # Vous pouvez combiner les deux techniques pour récupérer un nombre aléatoire # compris entre deux limites. nombre=0 #initialise while [ "$nombre" -le $PLANCHER ] do nombre=$RANDOM let "nombre %= $ECHELLE" # Met $nombre sous $ECHELLE. done echo "Nombre aléatoire compris entre $PLANCHER et $ECHELLE --- $nombre" echo # Génère un choix binaire, c'est-à-dire "vrai" ou "faux". BINAIRE=2 nombre=$RANDOM T=1 let "nombre %= $BINAIRE" # let "nombre >>= 14" donne une meilleure distribution aléatoire # (les décalages droits enlèvent tout sauf le dernier nombre binaire). if [ "$nombre" -eq $T ] then echo "VRAI" else echo "FAUX" fi echo # Peut générer des matrices (??). SPOTS=7 # Modulo 7 donne une échelle de 0 à 6. DICE=2 ZERO=0 die1=0 die2=0 # Jette chaque dé séparément, et donne ainsi une chance correcte. while [ "$die1" -eq $ZERO ] # Un zéro ne peut pas arriver. do let "die1 = $RANDOM % $SPOTS" # Le premier. done while [ "$die2" -eq $ZERO ] do let "die2 = $RANDOM % $SPOTS" # Le deuxième. done let "throw = $die1 + $die2" echo "Throw of the dice = $throw" echo exit 0 |
Exemple 9-24. Piocher une carte au hasard dans un tas
#!/bin/bash # pick-card.sh # Ceci est un exemple pour choisir au hasard un élément d'un tableau. # Prenez une carte, n'importe quelle carte. Suites="Carre Pique Coeur Trefle" Denominations="2 3 4 5 6 7 8 9 10 Jack Queen King Ace" suite=($Suites) # Mettre dans une variable de type tableau. denomination=($Denominations) num_suites=${#suite[*]} # Compter le nombre d'éléments. num_denominations=${#denomination[*]} echo -n "${denomination[$((RANDOM%num_denominations))]} of " echo ${suite[$((RANDOM%num_suites))]} # $bozo sh pick-cards.sh # Jack of Clubs # Merci, "jipe", pour m'avoir indiqué cette utilisation de $RANDOM. exit 0 |
![]() | Jipe nous a indiqué un autre ensemble de techniques pour générer des nombres aléatoires à l'intérieur d'un intervalle donné.
|
A quel point $RANDOM est-il aléatoire? la meilleur façon de le tester est d'écrire un script qui enregistre la suite des nombres << aléatoires >> générés par $RANDOM. Faisons tourner $RANDOM plusieurs fois...
Exemple 9-25. Laisser tourner RANDOM plusieurs fois
#!/bin/bash # A quel point RANDOM est aléatoire? RANDOM=$$ # Réinitialise le générateur de nombres aléatoires en utilisant #+ le PID du script. PIPS=6 # A die has 6 pips. COMPTEURMAX=600# Augmentez ceci, si vous n'avez rien de mieux à faire. compteur=0 # Compteur. zeros=0 # Doit initialiser les comptes à zéro. uns=0 # car une variable non initialisée est null, et ne vaut pas zéro. deux=0 trois=0 quatre=0 cinq=0 six=0 Affiche_resultat () { echo echo "uns = $uns" echo "deux = $deux" echo "trois = $trois" echo "quatre = $quatre" echo "cinq = $cinq" echo "six = $six" echo } mise_a_jour_compteur() { case "$1" in 0) let "uns += 1";; # Comme die n'a pas de "zéro", ceci correspond à 1. 1) let "deux += 1";; # Et ceci à 2, etc. 2) let "trois += 1";; 3) let "quatre += 1";; 4) let "cinq += 1";; 5) let "six += 1";; esac } echo while [ "$compteur" -lt "$COMPTEURMAX" ] do let "die1 = RANDOM % $PIPS" mise_a_jour_compteur $die1 let "compteur += 1" done Affiche_resultat # Les scores devraient être distribués de façon égale, en supposant que RANDOM #+ soit correctement aléatoire. # Avec $COMPTEURMAX à 600, tout devrait tourner autour de 100, plus ou moins #+ 20. # # Gardez en tête que RANDOM est un générateur pseudo-aléatoire, # et pas un particulièrement bon. # Exercice (facile): # --------------- # Réécrire ce script pour lancer une pièce 1000 fois. # Les choix sont "PILE" ou "FACE". exit 0 |
Comme nous avons vu sur le dernier exemple, il est préférable de << réinitialiser >> le générateur RANDOM à chaque fois qu'il est invoqué. Utiliser le même germe pour RANDOM ne fera que répéter la même série de nombres. (Ceci reflète le comportement de la fonction C random().)
Exemple 9-26. Réinitialiser RANDOM
#!/bin/bash # seeding-random.sh: Utiliser la variable RANDOM. NBMAX=25 # How many numbers to generate. nombres_aleatoires () { compteur=0 while [ "$compteur" -lt "$NBMAX" ] do nombre=$RANDOM echo -n "$nombre " let "compteur += 1" done } echo; echo RANDOM=1 # Initialiser RANDOM met en place le générateur de nombres #+ aléatoires. nombres_aleatoires echo; echo RANDOM=1 # Même élément pour RANDOM... nombres_aleatoires # ...reproduit la même série de nombres. # # Quand est-il utile de dupliquer une série de nombres #+ "aléatoires"? echo; echo RANDOM=2 # Nouvel essai, mais avec un 'seed' différent... nombres_aleatoires # donne une autre série... echo; echo # RANDOM=$$ initialise RANDOM à partir du PID du script. # Il est aussi possible d'initialiser RANDOM à partir des commandes 'time' et #+ 'date'. # Un peu plus d'amusement... SEED=$(head -1 /dev/urandom | od -N 1 | awk '{ print $2 }') # Sortie pseudo-aléatoire récupéré de /dev/urandom (fichier périphérique #+ pseudo-aléatoire), #+ puis convertit la ligne en nombres (octal) affichables avec "od". #+ Finalement "awk" récupère un seul nombre pour SEED. RANDOM=$SEED nombres_aleatoires echo; echo exit 0 |
![]() | Le fichier périphérique /dev/urandom apporte un moyen de générer des nombres pseudo aléatoires bien plus << aléatoires >> que la variable $RANDOM. dd if=/dev/urandom of=fichier_cible bs=1 count=XX crée un fichier de nombres pseudo aléatoires bien distribués. Néanmoins, assigner ces nombres à une variable dans un script nécessite un petit travail supplémentaire, tel qu'un filtrage par l'intermédiaire de od (comme dans l'exemple ci-dessus) ou tel que l'utilisation de dd (voir Exemple 12-42). Il existe aussi d'autres moyens de générer des nombres pseudo aléatoires dans un script. Awk propose une façon agréable de le faire. Exemple 9-27. Nombres pseudo aléatoires, en utilisant awk
|
Précédent | Sommaire | Suivant |
Références indirectes aux variables | Niveau supérieur | La construction en double parenthèse |