シェルで0始まり整数の演算をすると8進数演算になるので注意
シェルスクリプトで外部からデータを受け取り、簡単な四則演算をする処理があったのだが、特殊な数値の場合のみエラーとなる問題が発生した。よくよくデータを見ると、受け取る数値は”01”, “02”のように0始まりの固定2桁の数値フォーマットで、かつ数字が”08”、”09"のときだけエラーとなっていた。
結論から言うと、0始まりの数値を演算するときは8進数となり0〜7以外の数値(8,9)を使うとエラーになるためだった。
bashの場合
7以下の数値は8進数演算でも計算結果は正しい
$ echo $((01+01)) 2 $ echo $((05+05)) 10
08, 09を使うとエラー
$ echo $((01+08)) -bash: 01+08: value too great for base (error token is "08") $ echo $((01+09)) -bash: 01+09: value too great for base (error token is "09")
cshの場合
cshの場合も同様。
7以下の数値の場合はOK
% @ a = 01 + 05 % echo $a 6
08, 09の場合はエラー
% @ a = 01 + 08 @: Badly formed number.
cshの場合はエラーメッセージがややわかりづらい。
その他の算術用コマンド
exprコマンドは0始まりでも10進数で演算してくれるよう
$ expr 08 + 09 17
bcコマンドも正しく10進数で計算してくれるよう
$ echo "01 + 08" | bc 9
いっそsedで先頭0を除去してしまう
いっそsedコマンドで0始まりの数値を通常の数値に直してしまう。以下のコマンドで修正できる。先頭以外の0は影響なし。下のコマンドで直したあとに計算すれば10進数で計算してくれる。
$ echo "08" | sed -e 's/^0\+\([0-9]\+\)$/\1/' 8 $ echo "008" | sed -e 's/^0\+\([0-9]\+\)$/\1/' 8 $ echo "123" | sed -e 's/^0\+\([0-9]\+\)$/\1/' 123 $ echo "01010" | sed -e 's/^0\+\([0-9]\+\)$/\1/' 1010
まとめ
シェル変数の計算は0始まりで8進数演算になるが、exprやbcのような算術用のコマンドだと0始まりでも10進数で計算してくれるので、入力データが0始まりで正しく10進数計算させたい場合は、注意が必要。先頭の0をテキスト処理で削除するか、exprやbcなどの算術用コマンドで計算する必要がある。
以上!