/dev/random
コマンドラインで(または)を使用する方法を探しています。特に、このようなストリームを使用して乱数ストリーム(1行に1つの数字)を作成する/dev/urandom
方法を知りたいです。stdin
stdout
私は、機械アーキテクチャで基本的にサポートされているすべての数値型の乱数に興味があります。たとえば、64ビットアーキテクチャの場合、これには64ビット符号付き整数と符号なし整数と64ビット浮動小数点が含まれます。範囲に関する限り、さまざまな数値型の最大範囲は大丈夫です。
Perl、Pythonなどの汎用インタプリタを使用してこれらすべてを行う方法を知っていますが、シェルの「より簡単な」ツールを使用してこれらすべてを行う方法を知りたいです。 (そして「より簡単」とは、「非常に小さなUnixインストールでも使用できる可能性が高い」という意味です。)
既定では、この問題はコマンドラインでバイナリデータを文字列表現に変換する問題を軽減します。 (たとえば、次は機能しません:。printf '%f\n' $(head -c8 /dev/random)
)
シェルに依存しない答えを探しています。さらに、この質問では、/dev/random
との違いは/dev/urandom
重要ではありません。結果の意味が異なる場合がありますが、片側で動作するすべての手順が他方で動作することを期待しています。
以下に示す機能を生成するために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
)、シェルプログラミング技術が不足しているため、これは私がすばやく設定できる最善です。 (いつものようにコメントや改善を歓迎します。)
この練習で最も驚いたのは硬いシェルからプログラムを作成します。基本数値コンテンツ(例:16進浮動小数点値の読み取りまたは最大デフォルト浮動小数点値の取得)...
_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'
}
答え1
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
man od
より多くの情報を知りたい場合od
。
答え2
一部のシェル(例bash(1)
:)には、$RANDOM
乱数を提供する「変数」があります。
答え3
Bash 組み込みコマンドを使用することがod
。
((RND=((RANDOM<<15|RANDOM)<<15|RANDOM)<<15|RANDOM))
これにより、0 から 1,152,921,504,606,846,975 までの任意の数字が与えられます。モジュラー分割により、必要な範囲に絞り込むことができます。
実際の例として、ディスクをスタンバイモードで起動するためにハードドライブから任意のセクタを読み取るとします。私はこれを行うことができます:
#!/bin/bash
DEV=/dev/sda # Let's say that this is the device we want to spin up.
# Get the device geometry...
read -d- SIZE64 BS <<<$(blockdev --getsize64 --getbsz $DEV)
((SECTORS=SIZE64/BS)) # The total number of $BS-sized sectors on that device.
((RND=(RANDOM<<15|RANDOM)<<15|RANDOM)) # Generate a 45-bit random number.
((SECT=RND%SECTORS)) # The random sector that we will now read...
dd if=$DEV of=/dev/null bs=$BS skip=$SECT count=1 >/dev/null 2>&1
完璧。
(注:この例では、45ビットの任意の整数で十分で、60ビットの任意の整数よりも少し速いと思います。)
修正する:
上記のスピード主張の定量的サポートを提供するには:
~# time for i in {1..10000} ;do RND=$(od -An -N7 -tu8 /dev/urandom) ;done
real 0m45.647s
user 0m17.540s
sys 0m28.807s
~# time for i in {1..10000} ;do ((RND=((RANDOM<<15|RANDOM)<<15|RANDOM)<<15|RANDOM)) ;done
real 0m0.112s
user 0m0.105s
sys 0m0.007s
答え4
バージョン5.1または5.2以降、bashには$SRANDOM
32ビット乱数を提供する「変数」があります。