ふとした瞬間に「あ、ランダムな文字列生成したい」というときがあると思う。
そんなときのShellコマンドを紹介。
ランダムな文字列にも色々種類がある
今回生成するのは以下。
- ランダムな文字列生成(例:'ex792Lhk')
- ランダムな数字文字列生成(例:'189765')
- 指定範囲内のランダムな整数生成(例:1〜100の数字)
ランダム系によく使われるやつ
- /dev/random
- /dev/urandom
- od
上記は全てlinux系には最初から入っているっぽいので環境気にせず使える(UbuntuとかMacとか)。
random
とurandom
どっち使えばええんや問題があるらしいが、とりあえずurandom
を使ってれば良い。「urandomは乱数種を再利用するから安全性がァー」とかあるらしいが別にセキュリティに利用するわけでもないのでおk。
ランダムな文字列生成(例:'ex792Lhk')
# ランダムな文字列を生成。第一引数に桁数を指定。デフォルトは10。 alias randomStr='_generateRandomString' function _generateRandomString() { local length=${1:-10} cat /dev/urandom | base64 | fold -w $length | head -n 1 }
出力
$ randomStr Ry7pAIf2De # 20文字の文字列生成 $ randomStr 20 eiQC0aHDg18ffH6x3oUt
ランダムな数字文字列生成(例:'189765')
乱数ではなく数値文字列であることに注意。
# ランダムな数値文字列を生成。第一引数に桁数を指定。デフォルトは4。 alias randomStrNum='_generateRandomNumberStr' function _generateRandomNumberStr() { local length=${1:-4} od -vAn -to1 </dev/urandom | tr -d " " | fold -w $length | head -n 1 }
出力
$ randomStrNum 3311 # 10桁の数字文字列を生成 $ randomStrNum 10 3151543003
指定範囲内のランダムな整数生成(例:100を指定した場合、1〜100の数字)
# 指定範囲内のランダムな整数を生成。第一引数に範囲を指定。デフォルトは100。 alias randomNum='_generateRandomNumber' function _generateRandomNumber() { local range=${1:-100} awk 'BEGIN{srand();print int(rand() * '"${range}"')}' }
出力
$ randomNum 20 # 1~1000の範囲で乱数を生成 $ randomNum 1000 344
解説
cat /dev/urandom | base64 | fold -w $length | head -n 1
cat /dev/urandom
と打つと以下のように文字化けしたような出力が得られる
$ cat /dev/urandom ����5>�W�R>�v��n������ڡ2C��9ϔ@{hRiNɂ|�_�7�G�b�u^q��E6�$������/}~����QC�w��{��@̝���H�Y U���$/%2 ���WNp��y�a������}�u��{���@5�ţ��*�g[!��H�U������o:yKw� ...(略)
このままだと読めないのでbase64
でデコード。すると下記のように無限に文字列が出力される。Ctrl+C
で終了できる。
4HkkhYJXrKlApvoBlmcw+X8O45Xz9JHo149+vLRYEY3SYATpgzJK/uhPNwfU6YzagjpJS6JpXDhJUzdzCq3BI93AedrZ6iHRRaNnELFA4bsVpM4Aw3WyVa8VxDl4ryzh1ZTF1bKi7Std7s9hqNK6PHCKsWY90Cfzi/TmZ2fw05lgE001t8p9k3W9PX+um7fXowoinq9EVFLgAshKY4bl6slPCmPBcBrq1fa7tNUQfKdKrymlnxgYVSIBQN1vhLw5kDkh0o ...(略)
あとはお好きな方法で文字を切り取るだけ。
今回はfold -w
を使って、指定文字数で区切って改行させ、head -n 1
で先頭行だけ抽出させている。
od -vAn -to1 </dev/urandom | tr -d " " | fold -w $length | head -n 1
od
なんてコマンドこれを調べるまで全く知らなかったが、以下のサイトが詳しい。
標準入力を8進数や16進数にダンプしてくれるらしいので、これを乱数作成に利用する。
また、od -vAn -td4
など、10進数で出力してくれる-td4
や16進数の-tx4
をよく見るが、私は-to1
の8進数1バイトの出力を利用している。
理由としては桁数が綺麗に出力出来る&数字のみになるから。
-td4
だとマイナスが表示されてしまうし、-tx4
だと文字列と数字が混合してしまう。
$ od -vAn -td4 </dev/urandom -1821141382 -849610530 -1013568552 245312278 ... $ od -vAn -tx4 </dev/urandom 04177049 f189f437 367061e5 4e9b108e ...
あとはやってみればわかると思うが桁数を綺麗に表示するには3桁区切りの-to1
が一番扱いやすい。(-to1,-to2,-to4とか試すと面白い。)
tr -d " "
で空白を消した時に、思ったとおりの桁数が得られたのが-to1
だったってのもある。空白を消さなければ-to4
でもなんでもええんちゃうか。
$ od -vAn -to1 </dev/urandom 025 054 220 145 350 345 110 041 174 245 177 253 157 302 157 304 ...
awk 'BEGIN{srand();print int(rand() * '"${range}"')}'
これはもうシンプルにawkゲーですわ。便利だね、で終わらせましょう。
終わり
zshだと(bashにもあるのかな?)$RANDOM
という環境変数が用意されているが、使い勝手が悪いので却下した。
ちなみにふとした瞬間に「あ、ランダムな文字列生成したい」となったことはまだ一度もない。