ランダムデータを生成するには、/dev/random、/dev/urandom を使用します。

ランダムデータを生成するには、/dev/random、/dev/urandom を使用します。

/dev/randomコマンドラインで(または)を使用する方法を探しています。特に、このようなストリームを使用して乱数ストリーム(1行に1つの数字)を作成する/dev/urandom方法を知りたいです。stdinstdout

私は、機械アーキテクチャで基本的にサポートされているすべての数値型の乱数に興味があります。たとえば、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

コメント:

  1. hexdump代わりに、od私が望む方法で出力フォーマットを指定するより簡単な方法を提供するので、これを使用します。
  2. しかし、迷惑なことに、hexdump64ビット整数はサポートされていません(wtf???)。
  3. 機能へのインタフェースは改善が必要ですが(たとえば、インタフェースも-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には$SRANDOM32ビット乱数を提供する「変数」があります。

関連情報