こんにちは。久しぶりに投稿します。
なにがしたいのか
パスワード生成とか、何かと需要のあるランダム文字列を、コマンド1つでターンと出力できるようなモノを実装したかった。
結果
使い方は単純で、
rndstr
コマンドに必要に応じて以下のオプションを渡すだけ。
- -n
数字
- -a
英小文字
- -A
英大文字
- -m
マイナス(「-」 <-ハイフンですよね...)
- -u
アンダーバー(「_」)
- -L 20
長さ20の文字列を出力(省略すると長さ10)
- -C 10
10個の文字列を出力(省略すると1個)
このうち、naA
のいずれかのオプションがないとエラーを吐きます。
ソースコードはコチラ
実装
まず、shell scriptを書く。
1.標準の長さと標準個数を変数で用意
#!/bin/sh
LEN=10
CNT=1
2.getopts
を用いてオプションを設定
test
とか [ ~ ]
で実装もできますが、今回は便利なコマンドを使います。
冒頭で挙げたオプションについてそれぞれフラグを設定しつつ、正規表現パターンに関する処理も行います。(パターンは後ほど使います。)
ちなみに引数付きのオプションは$OPT
→$OPTARG
といった形で持ってこれます。
パターンを見ればわかりますが見間違いやすい文字を省いています。(数字の0と英字のo とか)
while getopts naAmuL:C: OPT
do
case $OPT in
"n" ) FLG_NUMBER="TRUE" ; PATTERN="${PATTERN}12345678" ;;
"a" ) FLG_small="TRUE" ; PATTERN="${PATTERN}abcdefghijkmnpqrstuvwxyz" ;;
"A" ) FLG_LARGE="TRUE" ; PATTERN="${PATTERN}ABCDEFGHIJKLMNPQRSTUVWXYZ" ;;
"m" ) FLG_MINUS="TRUE" ; PATTERN="${PATTERN}\-" ;;
"u" ) FLG_UBAR="TRUE" ; PATTERN="${PATTERN}_" ;;
"L" ) FLG_LENGTH="TRUE" ; LEN=$OPTARG ;;
"C" ) FLG_COUNT="TRUE" ; CNT=$OPTARG ;;
esac
done
3.エラー処理
フラグを利用して、「数字も英字もナシなんて許さないヨ」を実装します。
if [ -z "$FLG_NUMBER" ] && [ -z "$FLG_small" ] && [ -z "$FLG_LARGE" ] ; then
echo "下記を最低1つ指定してください。"
echo "[-n] 数字"
echo "[-a] 英小文字"
echo "[-A] 英大文字"
else
# ...
fi
4.色々縛りをかける
変数CONTAIN
に正規表現パターンを代入し、「数字指定したのに数字が含まれてない!」等を防止しています。
そして最後の1行で
-
cat /dev/urandom
... 乱数文字列を取得 -
tr -dc ${PATTERN}
...$PATTERN
以外の文字を削除- Mac OSでは
LC_CTYPE=C
を付さないとエラーが起きます。
- Mac OSでは
-
fold -w ${LEN}
...$LEN
行ごとに改行 -
grep -i "[${CONTAIN}]"
... 「数字指定したのに数字が含まれてない!」防止 -
grep -e '^[12
...YZ]'
... 先頭が記号以外 -
head -n ${CNT}
... 先頭$CNT
行だけ取得
という一連の処理を行い、必要なランダム文字列を取得することができます。
if [ -z "$FLG_NUMBER" ] && [ -z "$FLG_small" ] && [ -z "$FLG_LARGE" ] ; then
# ...
else
if [ -n "$FLG_MINUS" ] && [ -n "$FLG_UBAR" ] ; then
CONTAIN="\-_"
elif [ -n "$FLG_UBAR" ] ; then
CONTAIN="_"
elif [ -n "$FLG_MINUS" ] ; then
CONTAIN="\-"
elif [ -n "$FLG_NUMBER" ] ; then
CONTAIN="12345678"
else
CONTAIN="abcdefghijkmnpqrstuvwxyz"
fi
cat /dev/urandom | LC_CTYPE=C tr -dc ${PATTERN} | fold -w ${LEN} | grep -i "[${CONTAIN}]" | grep -e '^[12345678abcdefghijkmnpqrstuvwxyzABCDEFGHIJKLMNPQRSTUVWXYZ]' | head -n ${CNT}
fi
次に、保存&bashrc等に登録。
保存先は、ホームディレクトリに自作コマンド専用のディレクトリを作ってまとめておくと何かと楽です。
(今回は~/cmds/rndstr.sh
に保存します。)
ここで重要なのが権限です。shファイルを作っても実行権限がないと動きません。
chmod +x ~/cmds/rndstr.sh
で付与しておきましょう。
次に.bashrc
や.zshrc
などにコマンドを登録します。
alias rndstr='~/cmds/rndstr.sh'
この1行を足します。