Ich suche nach Möglichkeiten, /dev/random
(oder /dev/urandom
) über die Befehlszeile zu verwenden. Insbesondere möchte ich wissen, wie man einen solchen Stream verwendet stdin
, um Zufallszahlenströme zu schreiben stdout
(eine Zahl pro Zeile).
Ich interessiere mich für Zufallszahlen für alle numerischen Typen, die die Maschinenarchitektur nativ unterstützt. Bei einer 64-Bit-Architektur umfassen diese beispielsweise 64-Bit-Ganzzahlen mit und ohne Vorzeichen sowie 64-Bit-Gleitkommazahlen. In Bezug auf die Bereiche reichen die maximalen Bereiche für die verschiedenen numerischen Typen aus.
Ich weiß, wie man das alles mit Allzweck-Interpreten wie Perl, Python usw. macht, aber ich würde gerne wissen, wie man das mit "einfacheren" Werkzeugen aus der Shell macht. (Mit "einfacher" meine ich "eher verfügbar, selbst in einer sehr minimalen Unix-Installation".)
Grundsätzlich reduziert das Problem das Konvertieren von Binärdaten in ihre Zeichenfolgendarstellungen in der Befehlszeile. (ZB geht das nicht : printf '%f\n' $(head -c8 /dev/random)
.)
Ich suche nach muschelunabhängigen Antworten. Auch der Unterschied zwischen /dev/random
und /dev/urandom
ist für diese Frage nicht wichtig. Ich gehe davon aus, dass jedes Verfahren, das für das eine funktioniert, für das andere funktioniert, auch wenn die Semantik der Ergebnisse unterschiedlich sein kann.
Ich habe die Antwort von EightBitTony angepasst, um die toints
unten gezeigten Funktionen usw. zu erzeugen .
Anwendungsbeispiel:
% < /dev/urandom toprobs -n 5
0.237616281778928
0.85578479125532
0.0330049682019756
0.798812391655243
0.138499033902422
Bemerkungen:
- Ich verwende
hexdump
statt,od
weil es mir eine einfachere Möglichkeit gab, die Ausgabe so zu formatieren, wie ich es wollte. - Ärgerlicherweise werden
hexdump
64-Bit-Ganzzahlen (wtf ???) nicht unterstützt. - Die Funktionen Schnittstelle muss arbeiten (zB sollte akzeptieren ,
-n5
als auch-n 5
), aber meine klägliche Shell - Programmierung skillz gegeben, das war das Beste , was ich schnell zusammen setzen könnte. (Kommentare / Verbesserungen sind wie immer willkommen.)
Die große Überraschung, die ich durch diese Übung bekam, war herauszufinden, wie schwierig es ist, die elementarsten numerischen Dinge auf der Shell zu programmieren (z. B. einen hexadezimalen Gleitkommawert lesen oder den maximalen nativen Gleitkommawert erhalten) ...
_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
sollte Ihnen nur eine Ganzzahl geben.