値が整数であるかどうか確認する。
成果物
結論
IsInt() { test 0 -eq $1 > /dev/null 2>&1 || expr $1 + 0 > /dev/null 2>&1; }
よく見かける
expr
だけの奴はバグがある。
ネット上では以下コードで数値判定できるような記事を見かける。
IsInt() { expr $1 - 1 > /dev/null 2>&1; }
しかし、-1
のときfalse
になってしまうバグがある。
$ IsInt -1 && echo 'Int' || echo 'NotInt' NotInt
それ以外の整数値なら負数であってもtrue
になる。
$ IsInt -2 && echo 'Int' || echo 'NotInt' Int
原因は、expr -1 + 1
が0
になりfalse
となってしまうため。
対策
対策は、計算結果が0
になる場合の入力値のみ個別に判定すること。
IsInt() { test -1 -eq $1 || expr $1 + 1 > /dev/null 2>&1; }
test
で数値比較できない値が入るとエラー文言が出力されてしまう。それを> /dev/null 2>&1
で消す。
IsInt() { test -1 -eq $1 > /dev/null 2>&1 || expr $1 + 1 > /dev/null 2>&1; }
expr $1 + 1
すると最大値が使えなくなってしまう。妥協案としてexpr $1 - 1
に変更して最小値を使えないようにする。計算結果が0
になる値の個別チェックもこれに伴い変更する。
IsInt() { test 1 -eq $1 > /dev/null 2>&1 || expr $1 - 1 > /dev/null 2>&1; }
最大値、最小値、どちらも使えるようにしたい。そこでexpr $1 + 0
とした。(expr $1 + 1
でもexpr $1 - 1
でもなく) 計算結果が0
になる値の個別チェックもこれに伴い変更する。
IsInt() { test 0 -eq $1 > /dev/null 2>&1 || expr $1 + 0 > /dev/null 2>&1; }
以上。
使い方
true
。
IsInt 0 && echo 'Int' || echo 'NotInt' IsInt 1 && echo 'Int' || echo 'NotInt' IsInt 2 && echo 'Int' || echo 'NotInt' IsInt -1 && echo 'Int' || echo 'NotInt' IsInt -2 && echo 'Int' || echo 'NotInt' IsInt 9223372036854775807 && echo 'Int' || echo 'NotInt' IsInt -9223372036854775807 && echo 'Int' || echo 'NotInt'
false
。
IsInt A && echo 'Int' || echo 'NotInt' IsInt 0.1 && echo 'Int' || echo 'NotInt' IsInt 9223372036854775808 && echo 'Int' || echo 'NotInt' IsInt -9223372036854775808 && echo 'Int' || echo 'NotInt'
最大値:9223372036854775807
$ expr 9223372036854775807 + 1 expr: +: 計算結果は範囲外の値です $ expr 9223372036854775806 + 1 9223372036854775807
最小値:-9223372036854775808
$ expr -9223372036854775808 - 1 expr: -: 計算結果は範囲外の値です $ expr -9223372036854775807 - 1 -9223372036854775808
問題
- 最小値〜最大値の範囲外はたとえ整数値であっても
false
になる - 浮動小数は対象外(
false
になる)
最小値〜最大値の範囲外はたとえ整数値であってもfalse
になる
仕方ない。Bash言語仕様の限界。
浮動小数は対象外(false
になる)
IsInt 0.1 && echo 'Int' || echo 'NotInt' # NotInt
IsInt
に浮動小数を渡せばfalse
が返る。
Bashでは浮動小数を扱えない。整数のみ。bc
コマンドで扱えるが、Raspbianにはデフォルトでインストールされていない。また、.1
のように最初の0
を省略せねばならないなどのクセがある。
対象環境
- Raspbierry pi 4 Model B
- Raspbian buster 10.0 2019-09-26 ※
- bash 5.0.3(1)-release
$ uname -a Linux raspberrypi 4.19.75-v7l+ #1270 SMP Tue Sep 24 18:51:41 BST 2019 armv7l GNU/Linux