web-dev-qa-db-ja.com

Bashで乱数を生成する方法は?

Bashの範囲内で乱数を生成する方法は?

179
woakas

$RANDOM を使用します。多くの場合、単純なシェル演算と組み合わせて使用​​すると便利です。たとえば、1〜10の乱数を生成するには:

$ echo $((1 + RANDOM % 10))
3

実際のジェネレーターはvariables.c、関数brand()にあります。 旧バージョン は単純な線形ジェネレーターでした。 bashのバージョン4.0では、1985年の論文で 引用付きのジェネレーター を使用しています。シミュレーションには使用しません(もちろん暗号化にも使用しません)が、基本的なスクリプト作成タスクにはおそらく十分でしょう。

深刻な乱数を必要とすることをしている場合は、/dev/randomまたは/dev/urandomを使用できます(使用可能な場合)。

$ dd if=/dev/urandom count=4 bs=1 | od -t d
217
Nelson

$RANDOM を参照してください:

$RANDOMは、0〜32767の範囲の擬似乱数整数を返す(定数ではなく)内部Bash関数です。暗号化キーの生成には使用しないでください。

63
Andrew Hare

シェルからこれを試してください:

$ od -A n -t d -N 1 /dev/urandom

ここで、-t dは、出力形式が符号付き10進数であることを指定します。 -N 1は、/dev/urandomから1バイトを読み取るように指示します。

32
Barun

shuf(coreutilsで使用可能)も使用できます。

shuf -i 1-100000 -n 1
27
knipwim

また、awkから乱数を取得することもできます

awk 'BEGIN {
   # seed
   srand()
   for (i=1;i<=1000;i++){
     print int(1 + Rand() * 100)
   }
}'
19
ghostdog74

$ RANDOMがあります。どのように機能するのか正確にはわかりません。しかし、それは機能します。テストのために、次のことができます。

echo $RANDOM
18
Antoine Claval

0から9までの乱数。

echo $((RANDOM%10))
10
David Newcomb

私はこのトリックが好きです:

echo ${RANDOM:0:1} # random number between 1 and 9
echo ${RANDOM:0:2} # random number between 1 and 99

...

8
fraff

Linuxシステムを使用している場合は、 / dev/random or /dev/urandomから乱数を取得できます。十分な乱数が利用できない場合、/ dev/randomがブロックすることに注意してください。ランダム性よりも高速が必要な場合は、/ dev/urandomを使用します。

これらの「ファイル」には、オペレーティングシステムによって生成された乱数が格納されます。真または擬似乱数を取得する場合、システム上の/ dev/randomの実装に依存します。真の乱数は、マウス、ハードドライブ、ネットワークなどのデバイスドライバーから収集されたノイズを形成するのに役立ちます。

dd でファイルから乱数を取得できます

5
Janusz

/ dev/randomまたは/ dev/urandomの文字特殊ファイルから読み取る方法があります。

これらのデバイスは、読み取られたときに真に乱数を返し、アプリケーションソフトウェアが暗号化用の安全なキーを選択できるように設計されています。このような乱数は、さまざまなランダムイベントによって提供されるエントロピープールから抽出されます。 {LDD3、ジョナサン・コーベット、アレッサンドロ・ルビニ、グレッグ・クローア・ハートマン]

これらの2つのファイルは、カーネルのランダム化、特に

void get_random_bytes_Arch(void* buf, int nbytes)

そのような機能が実装されたハードウェアによるものである場合(通常はそうである場合)、ハードウェアから真にランダムなバイトを引き出します。

dd if=/dev/urandom count=4 bs=1 | od -t d

これは機能しますが、ddから不要な出力をstdoutに書き込みます。以下のコマンドは、必要な整数のみを提供します。算術展開に与えられたビットマスクを調整することで、必要に応じて指定された数のランダムビットを取得することもできます。

me@mymachine:~/$ x=$(head -c 1 /dev/urandom > tmp && hexdump 
                         -d tmp | head -n 1 | cut -c13-15) && echo $(( 10#$x & 127 ))
4
4pie0

これらのアイデアのいくつかを取り入れて、大量の乱数が必要な場合に迅速に実行される機能を作成しました。

odの呼び出しは、大量の乱数が必要な場合には費用がかかります。代わりに、1回呼び出して、/ dev/urandomから1024個の乱数を保存します。 Randが呼び出されると、最後の乱数が返され、スケーリングされます。その後、キャッシュから削除されます。キャッシュが空の場合、さらに1024個の乱数が読み取られます。

例:

Rand 10; echo $RET

0から9までのRETの乱数を返します。

declare -ia RANDCACHE
declare -i RET RAWRAND=$(( (1<<32)-1 ))

function Rand(){  # pick a random number from 0 to N-1. Max N is 2^32
  local -i N=$1
  [[ ${#RANDCACHE[*]} -eq 0 ]] && { RANDCACHE=( $(od -An -tu4 -N1024 /dev/urandom) ); }  # refill cache
  RET=$(( (RANDCACHE[-1]*N+1)/RAWRAND ))  # pull last random number and scale
  unset RANDCACHE[${#RANDCACHE[*]}-1]     # pop read random number
};

# test by generating a lot of random numbers, then effectively place them in bins and count how many are in each bin.

declare -i c; declare -ia BIN

for (( c=0; c<100000; c++ )); do
  Rand 10
  BIN[RET]+=1  # add to bin to check distribution
done

for (( c=0; c<10; c++ )); do
  printf "%d %d\n" $c ${BIN[c]} 
done

更新:それはすべてのNでそれほどうまく機能しません。小さなNで使用すると、ランダムビットも無駄になります。 9 = 1,000,000,000 <= 2 * 32)32個のランダムソース値から複数の乱数を抽出できます。

#!/bin/bash

declare -ia RCACHE

declare -i RET             # return value
declare -i ENT=2           # keep track of unused entropy as 2^(entropy)
declare -i RND=RANDOM%ENT  # a store for unused entropy - start with 1 bit

declare -i BYTES=4         # size of unsigned random bytes returned by od
declare -i BITS=8*BYTES    # size of random data returned by od in bits
declare -i CACHE=16        # number of random numbers to cache
declare -i MAX=2**BITS     # quantum of entropy per cached random number
declare -i c

function Rand(){  # pick a random number from 0 to 2^BITS-1
  [[ ${#RCACHE[*]} -eq 0 ]] && { RCACHE=( $(od -An -tu$BYTES -N$CACHE /dev/urandom) ); }  # refill cache - could use /dev/random if CACHE is small
  RET=${RCACHE[-1]}              # pull last random number and scale
  unset RCACHE[${#RCACHE[*]}-1]  # pop read random number
};

function randBetween(){
  local -i N=$1
  [[ ENT -lt N ]] && {  # not enough entropy to supply ln(N)/ln(2) bits
    Rand; RND=RET       # get more random bits
    ENT=MAX             # reset entropy
  }
  RET=RND%N  # random number to return
  RND=RND/N  # remaining randomness
  ENT=ENT/N  # remaining entropy
};

declare -ia BIN

for (( c=0; c<100000; c++ )); do
  randBetween 10
  BIN[RET]+=1
done

for c in ${BIN[*]}; do
  echo $c
done
4
philcolbourn

どうですか:

Perl -e 'print int Rand 10, "\n"; '
2
k-h

少し遅すぎるかもしれませんが、jotを使用してBashの範囲内で乱数を生成するのはどうでしょうか。

jot -r -p 3 1 0 1

これにより、小数点以下3桁の精度(-r)でランダム(-p)番号が生成されます。この特定のケースでは、0〜1の間の1つの数字(1 0 1)を取得します。順次データを印刷することもできます。マニュアルによると、乱数のソースは次のとおりです。

乱数は、シードが指定されていない場合はarc4random(3)を介して取得され、シードが指定されている場合はrandom(3)を介して取得されます。

2
Vinicius Placco

0からn(符号付き16ビット整数)の範囲の乱数を生成します。 $ Rand変数の結果セット。例えば:

#!/bin/bash

random()
{
    local range=${1:-1}

    Rand=`od -t uI -N 4 /dev/urandom | awk '{print $2}'`
    let "Rand=$Rand%($range+1)"
}

n=10
while [ $(( n -=1 )) -ge "0" ]; do
    random 500
    echo "$Rand"
done
1
Pavel Bashinsky