Je cherche des moyens d'utiliser /dev/random
(ou /dev/urandom
) à partir de la ligne de commande. En particulier, j'aimerais savoir comment utiliser un tel flux stdin
pour écrire des flux de nombres aléatoires vers stdout
(un numéro par ligne).
Je suis intéressé par les nombres aléatoires pour tous les types numériques pris en charge nativement par l'architecture de la machine. Par exemple, pour une architecture 64 bits, ceux-ci comprendraient des entiers signés et non signés 64 bits et des nombres à virgule flottante 64 bits. En ce qui concerne les plages, les plages maximales pour les différents types numériques feront l'affaire.
Je sais comment faire tout cela avec des interprètes polyvalents comme Perl, Python, etc., mais j'aimerais savoir comment le faire avec des outils "plus simples" du shell. (Par "plus simple", je veux dire "plus susceptible d'être disponible même dans une installation Unix très minimale".)
Fondamentalement, le problème réduit celui de la conversion des données binaires en leurs représentations de chaîne sur la ligne de commande. (Par exemple, cela ne fera pas:. printf '%f\n' $(head -c8 /dev/random)
)
Je cherche des réponses indépendantes de l'environnement. En outre, la différence entre /dev/random
et /dev/urandom
n'est pas importante pour cette question. Je m'attends à ce que toute procédure qui fonctionne pour l'un fonctionne pour l'autre, même lorsque la sémantique des résultats peut différer.
J'ai adapté la réponse d'EightBitTony pour produire les fonctions toints
, etc. ci-dessous.
Exemple d'utilisation:
% < /dev/urandom toprobs -n 5
0.237616281778928
0.85578479125532
0.0330049682019756
0.798812391655243
0.138499033902422
Remarques:
- J'utilise
hexdump
au lieu deod
parce que cela m'a donné un moyen plus facile de formater la sortie comme je le voulais; - Malheureusement,
hexdump
ne prend pas en charge les entiers 64 bits (wtf ???); - L'interface des fonctions a besoin de travail (par exemple, elles devraient accepter
-n5
aussi bien que-n 5
), mais étant donné mes pitoyables compétences en programmation shell, c'était le mieux que j'ai pu assembler rapidement. (Commentaires / améliorations bienvenus, comme toujours.)
La grande surprise que j'ai eue de cet exercice a été de découvrir à quel point il est difficile de programmer sur le shell les éléments numériques les plus élémentaires (par exemple lire un flottant hexadécimal, ou obtenir la valeur flottante native maximale) ...
_tonums () {
local FUNCTION_NAME=$1 BYTES=$2 CODE=$3
shift 3
local USAGE="Usage: $FUNCTION_NAME [-n <INTEGER>] [FILE...]"
local -a PREFIX
case $1 in
( -n ) if (( $# > 1 ))
then
PREFIX=( head -c $(( $2 * $BYTES )) )
shift 2
else
echo $USAGE >&2
return 1
fi ;;
( -* ) echo $USAGE >&2
return 1 ;;
( * ) PREFIX=( cat ) ;;
esac
local FORMAT=$( printf '"%%%s\\n"' $CODE )
$PREFIX "$@" | hexdump -ve $FORMAT
}
toints () {
_tonums toints 4 d "$@"
}
touints () {
_tonums touints 4 u "$@"
}
tofloats () {
_tonums tofloats 8 g "$@"
}
toprobs () {
_tonums toprobs 4 u "$@" | perl -lpe '$_/=4294967295'
}
tr -cs '[:digit:]' '[\n*]' </dev/urandom
devrait vous donner uniquement un nombre entier.