こやつに数日悩まされていたので…
manからの抜粋
expr は終了時に以下のような値を返す。
0: 式がヌルでも 0 でもなかった場合。
1: 式がヌルまたは 0 だった場合。
2: 式が正しくなかった場合。
- 式がヌルまたは 0 だった場合 がミソ。
嵌る例
- 下記bash scriptは OKが表示されずに終了します。
#!/bin/sh
set -ex
a=`expr 2 + 5 - 7`
echo "OK!"
exit 0
-
set -e
とは何ぞや?という話になりそうですが、これは各コマンドで0以外のステータスが帰ってきたら終了するオプションとなります。 - なんで、OKが出ないのよ?というのは、 expr の式評価時にexpr 自体が戻り値1を返してくるので変数aに代入した時点で、set -e の制約に引っかかり、終了する という事が起こります。
回避例
-
googleさんに尋ねると幾つか見つかりますね…
- [Bash] letによる四則演算 http://sweng.web.fc2.com/ja/program/bash/bash-let.html
- [Bash] 二重括弧による四則演算 http://sweng.web.fc2.com/ja/program/bash/bash-calc.html
- [Unix command] bcによる少数の演算 http://sweng.web.fc2.com/ja/program/shellscript/bc.html
-
個人的には「二重括弧で計算」が一番スマートかな、と。(bash限定になってしまうのが問題といえば問題ですが)。ちなみに二重括弧に置き換えるとこうなります。
#!/bin/sh
set -ex
a=$((2 + 5 - 7))
echo "OK!"
exit 0
- ちなみに上記は「OK!」の文字が出て0が返ります。
それじゃ expr って悪なの?
- それじゃ、expr禁止令?と思われがちですが、そーでもない感じです。例えばこういうパターンにexprが活躍したりします。
#!/bin/sh
if [ $# -lt 1 ] ; then
echo "error." ; exit 1
elif expr "$1" : ^[0-9]*$ > /dev/null ; then
echo "number." ; exit 0
else
echo "not number." ; exit 1
fi
簡単な数値パターンマッチングですね。0~9しか存在しなければ expr が 0 を返すので数値と判定する、というオチです。
追記 : expr 使っても 戻り値1 を検知しないパターンが存在する模様
- 下記パターンはexprを使っても戻り値1を拾わずにエラーにならないようです。echoがexprの戻り値を見ないで捨てるのでOKとか、ですかね…?(仕組みはよくわからん)
#!/bin/sh
set -ex
echo `expr 2 + 5 - 7`
exit 0