よくある話だが、やり方をうろ覚えだったので、改めて調べてみた。ちょっと検索してみると、大きく2種類の実装方法があった。
- 数値演算をやってみて、エラーをひろう方法
- 値が数値のみで構成されているかを調べる方法
なるほど。どちらの方法でもよいと思う。
後者については、検索結果として、次のようなサイトが(比較的)上位に出てきた。でも、これらはちょっとだけ問題だと思う。
NUMERIC_CHECK=`echo "${1}" | awk '/[^0-9]/ {print}'` if [[ ! -z $NUMERIC_CHECK ]] then echo "not numeric" else echo "numeric" fi
A=`echo -n $1|sed 's/[0-9]//g' ` if [ -n "$A" ]; then echo "文字列も含まれます。" else echo "数値だけです。" fi
《modules:bwiki:index.php [fl8 Wiki]より》
やっていることは、「正規表現で数値部分を除去し、残った部分が空であれば、元々の値が数値である」というチェックロジックだ。で、何がまずいかというと、元々の値が空であることが想定されていない点である。例えば、次のようにスクリプトを実行すると、第1引数は数値ではないが、チェックは通ってしまう。
/example/some_script.sh "" "abc" 123
なので、この方法を使うのであれば、次のように*1元々の値が空でないこともチェックすべきではないだろうか。
arg1=${1} expect_empty=`echo -n ${arg1} | sed 's/[0-9]//g'` if [ "x" = "x${arg1}" ] || [ "x" != "x${expect_empty}" ] then echo "引数1の値 ${arg1} が、数値ではありません。" fi
ど?
2011/04/21追記
この方法は、数値チェックというよりも、ゼロと自然数チェックだな。小数もダメだし、負の数もダメ。なのに“0000001”や“00”のような文字列っぽい値も数値としてしまう。もう少し考慮が必要だ。
*1:むろん、testコマンドの表現(if文の条件)は“-n”なり“-z”なりを用いてもよい。シェルの人ではない人でも、読みやすくしているだけ。あと“||”でなくtestコマンドの表現である“-o”を使うこともできるが、こっちは可読性ではなく、より効率的かなと思って。