コマンドラインから_/dev/random
_(または_/dev/urandom
_)を使用する方法を探しています。特に、stdin
などのストリームを使用して、乱数のストリームをstdout
(1行に1つの数値)に書き込む方法を教えてください。
マシンのアーキテクチャがネイティブでサポートしているすべての数値型の乱数に興味があります。例えば。 64ビットアーキテクチャの場合、これらには64ビットの符号付き整数と符号なし整数、および64ビット浮動小数点数が含まれます。範囲に関する限り、さまざまな数値タイプの最大範囲で十分です。
Perl、Pythonなどの多目的インタープリターでこれを行う方法を知っていますが、シェルの「より単純な」ツールでこれを行う方法を知りたいです。 (「より単純」とは、「最小限のUnixインストールでも利用できる可能性が高い」という意味です。)
基本的に、この問題により、コマンドラインでバイナリデータを文字列表現に変換する問題が軽減されます。 (たとえば、これは機能しません:printf '%f\n' $(head -c8 /dev/random)
。)
シェルにとらわれない答えを探しています。また、_/dev/random
_と_/dev/urandom
_の違いは、この質問では重要ではありません。結果のセマンティクスが異なる場合でも、1つの手順で機能する手順が他の手順でも機能することを期待しています。
EightBitTonyの回答を適用して、以下に示す関数toints
などを生成しました。
使用例:
_% < /dev/urandom toprobs -n 5
0.237616281778928
0.85578479125532
0.0330049682019756
0.798812391655243
0.138499033902422
_
備考:
hexdump
の代わりにod
を使用しています。これは、出力を希望どおりにフォーマットする簡単な方法を提供するためです。hexdump
は64ビット整数(wtf ???)をサポートしていません。-n5
_と_-n 5
_を受け入れる必要があります)。 (いつものように、コメント/改善は歓迎します。)私がこの演習で得た大きな驚きは、シェルでプログラムすることhardがどのようにmost elementary数値のものであるかを発見することでした(たとえば、16進数の浮動小数点数を読み取る、または最大値を取得する)ネイティブfloat値)...
__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'
}
_
od
を使用すると、/dev/random
および/dev/urandom
から数値を取得できます。
例えば、
2バイトの符号なし10進整数、
$ od -vAn -N2 -tu2 < /dev/urandom
24352
1バイトの符号付き10進整数、
$ od -vAn -N1 -td1 < /dev/urandom
-78
4バイトの符号なし10進整数、
$ od -vAn -N4 -tu4 < /dev/urandom
3394619386
od
の詳細については、man od
をご覧ください。
一部のシェル(bash(1)
など)には$RANDOM
乱数を与える「変数」。
あなたは次のようなことをすることができます:
Perl -le '
while (q(
c char, C unsigned char, s! short, S! unsigned short,
i! int, I! unsigned int, l! long, L! unsigned long,
f float, d double,) =~ /(\S+) (.*?),/gs) {
$size = length(pack $1, 0);
sysread STDIN, $data, $size;
print "$2($size): " . unpack($1, $data);
}' < /dev/urandom
64ビットシステムでは、次のようになります。
char(1): -98
unsigned char(1): 62
short(2): -12526
unsigned short(2): 399
int(4): 499066219
unsigned int(4): 2312134917
long(8): -4889591208978026255
unsigned long(8): 2080566823379835456
float(4): 55.4727554321289
double(8): 8.6395690272822e-05