UNIX/Linuxの部屋 用語集:ランダム・乱数まとめ

TOP UNIX/Linuxの部屋 UNIX/Linuxコマンド一覧 用語集 新版 由来/読み方辞書 環境変数マニュアル Cシェル変数 システム設定ファイル システムコール・ライブラリ ネットワークプログラミングの基礎知識 クラウドサービス徹底比較・徹底解説




用語集 ランダム・乱数まとめ ランダムな、数値・数字・16進数文字列・バイナリデータ・パスワードなどの生成・出力方法 このエントリーをはてなブックマークに追加

最終更新


UNIX・Linux で、シェルスクリプトから使うことができるランダムな数値・乱数・文字列などの作成方法を紹介する。openssl・jot・$RANDOM・/dev/urandom・awk など、いろいろなやりかたがある。



openssl rand を使う
100 バイトのランダムなバイナリデータを生成し、file に出力する。
% openssl rand 100 > file
10 バイトのランダムデータを 16進数として出力する
% openssl rand -hex 10
d5e6809fa57b7db12610
→ 1バイト2文字なので、20文字となる
% openssl rand -hex 10 | tr a-z A-Z
C287E323911E5357A6FF
→ 大文字の16進数にする場合は tr で
% openssl rand -hex 10 | tr a-z A-Z | sed 's/\(..\)/\1 /g'
D0 3E 27 F4 86 2F 7C EE AD E4
→ 1バイトずつスペースを入れてみた
16 バイトのランダムデータを BASE64 形式で出力する
% openssl rand -base64 16
9zW8RaU/y+EkJ+G/4UcgtQ==

jot -r を使う
*BSD 系なら jot -r が使える。
% jot -r 5
19
26
78
68
75
⇒ 1〜100 のランダムな数字を 5 個表示する。
% jot -r 5 0 255
82
219
248
44
185
⇒ 0〜255 のランダムな数字を 5 個表示する。

bash・zsh なら $RANDOM
bash・zsh には、参照するたびに 0〜32767 の範囲の異なる値を返す $RANDOM というシェル変数が用意されている。
% echo $RANDOM
3999
% echo $RANDOM
9460
% echo $RANDOM
21428

0〜15 の数を 10回取得したい場合
% for i in `seq 1 10`; do echo $(( $RANDOM % 15 )); done;
→ bash では成功したが zsh では同じ値が返ってきてしまう
% for i in `seq 1 10`; do echo `expr $RANDOM % 15`; done;
→ こちらは bash・zsh いずれも OK のようだ

/dev/random・/dev/urandom から
dd でバイナリデータを 10バイト取得
% dd if=/dev/urandom bs=1 count=10 > x
head で 10バイト
% head -c 10 < /dev/urandom > x
od で値を取得
% od -vAn -N1 -tu4 < /dev/urandom
→ 1バイト取得 (0〜255)
% od -vAn -N2 -tu4 < /dev/urandom
→ 2バイト取得 (0〜65535)
% od -vAn -N4 -tu4 < /dev/urandom
→ 4バイト取得 (0〜4294967296)
% echo $((`od -vAn -N2 -tu4 < /dev/urandom` % 100))
→ 100の余りをとって、0〜99 を取得
10バイト取得し、base64 化
% cat /dev/urandom | head -c 10 | base64
ftnLS5s5txujrA==
20個の数字を取得
% env LC_ALL=C tr -dc 0-9 < /dev/urandom | fold -w 20 | head -1
57288818183277636892
20個の英数字 (小文字) を取得
% env LC_ALL=C tr -dc a-z0-9 < /dev/urandom | fold -w 20 | head -1
5brs7zog87raykb4wjuq
20個の英数字 (大文字小文字混在) を取得
% env LC_ALL=C tr -dc a-zA-Z0-9 < /dev/urandom | fold -w 20 | head -1
rLDAIXmzArDfDZuQ3r8e
20個の英数字 (大文字小文字記号混在) を取得。パスワード生成に使える。
% env LC_ALL=C tr -dc 'a-zA-Z0-9~!@#$%^&*_-' < /dev/urandom | fold -w 20 |head -1
E7!SZjhqT$wQd@r_k6C0

sort や shuf で行の並べ替え
新しめの GNU sort であればランダムにソートする -R オプションがあるかもしれない。
% sort -R < file.txt
→ ファイルから
% seq 1 10 | sort -R
→ 1〜10 の連番をランダムに並べ替え
% jot 10 | sort -R
→ seq コマンドがなければ jot で
sort -R の場合、ハッシュでソートするため、同じ行があると固まって出力されてしまう。重複値が隣り合うと困る場合は、shuf コマンドを使うとよい。

% for i in 1 2 2 2 3 3 3 3 3 4 5 6 7 8 ; do echo $i ; done | sort -R
→ sort -R だと 2 や 3 が必ず隣り合って出力される
% for i in 1 2 2 2 3 3 3 3 3 4 5 6 7 8 ; do echo $i ; done | shuf
→ shuf コマンドだと大丈夫

shuf コマンドであれば、以下のようなこともできる。
% cat file.txt | shuf -n 1
→ ファイルの中からランダムに 1行出力
% cat file.txt | shuf -n 3
→ ファイルの中からランダムに 3行出力

N% の確率で〜する
bash・zsh なら $RANDOM で
if [ $(($RANDOM % 100)) -lt 5 ]; then
echo "5%の確率"
fi
$RANDOM が使えないなら
num=`env LC_ALL=C tr -dc 0-9 < /dev/urandom | fold -w 2 | head -1`
if [ $num -lt 5 ]; then
echo "5%の確率"
fi

awk で
awk で 0〜99 を 10回出力
% awk 'BEGIN {srand(); for (i=1;i<=10;i++) print int(rand()*100)}'
→ srand は秒で初期化しているので、1秒以内に複数回実行すると同じ値が返ってくることに注意