シェルスクリプトでは、_expr $a*$b
_を$(($a+$b))
に置き換えることができます。
しかし、なぜ_(($a+$b))
_だけでなく、どのリソースでも_(())
_は整数計算用であると書かれているからです。
それで、整数値の代わりに変数があるときに$(())
を使用しますか?また、変数が浮動小数点値を受け取ることができる場合、$(())
の代わりに何を使用する必要がありますか?
算術の場合、expr
は古風です。使用しないでください。*
$((...))
と_((...))
_はよく似ています。どちらも整数計算のみを行います。違いは、$((...))
は計算の結果を返し、_((...))
_は返さないことです。したがって、$((...))
はecho
ステートメントで役立ちます。
_$ a=2; b=3; echo $((a*b))
6
_
_((...))
_は、変数を割り当てたり、終了コードを設定したりするときに便利です。
_$ a=3; b=3; ((a==b)) && echo yes
yes
_
浮動小数点計算が必要な場合は、bc
またはawk
を使用します。
_$ echo '4.7/3.14' | bc -l
1.49681528662420382165
$ awk 'BEGIN{print 4.7/3.14}'
1.49682
_
*余談ですが、expr
は、グロブが十分ではなく、正規表現を処理するためにPOSIXメソッドが必要な場合でも、文字列処理に役立ちます。
exprは古いですが、私が考えることができる1つの限られた用途があります。文字列を検索したいとします。 grepでPOSIXを維持したい場合は、パイプを使用する必要があります。
_if echo november | grep nov
then
: do something
fi
_
exprはパイプなしでこれを行うことができます:
_if expr november : nov
then
: do something
fi
_
唯一の問題は、exprがアンカー文字列で機能することです。そのため、開始後に一致させたい場合は、REGEXPを変更する必要があります。
_if expr november : '.*ber'
then
: do something
fi
_
_(( ))
_に関しては、この構成 はPOSIXではない なので、回避する必要があります。
$(( ))
については、ドル記号を含める必要はありません。
_$ fo=1
$ go=2
$ echo $((fo + go))
3
_
以下のプログラムは多かれ少なかれ同じように動作し、実際には違いはないようです。しかし、それは真実ではありません。
#!/bin/bash
s=-1000
for (( i=0; i<1000000; i++ )), do
s=$((s+1))
echo $s
これは、これを実装する正しい方法です。式s + 1はシェルによって評価され、変数に割り当てることができます。
#!/bin/bash
s=-1000
for (( i=0; i<1000000; i++ )), do
s=`expr $s+1`
echo $s
ここで、式はシェル組み込みではなく外部Unixプログラムであるプログラムexprによって計算されます。したがって、単純に1とsを追加する代わりに、プログラムを開始し、その出力を変数に読み書きする必要があります。プログラムを開始するには、多くのリソースと時間が必要です。そして、このプログラムは1000000回実行されます。したがって、プログラムは以前よりもはるかに遅くなります。それにもかかわらず、コードは正しく動作します。
#!/bin/bash -e
s=-1000
for (( i=0; i<1000000; i++ )), do
((s=s+1))
echo $s
-eフラグが設定されていない場合、プログラムも正しく動作します。ただし、s = -1および((s = s + 1))が計算されるときに-eが設定されている場合。式s = s + 1は0に評価され、((0))の終了コードは> 0であり、シェルによってエラーとして解釈され、シェルはプログラムを終了します。
-eフラグを設定する理由は、これがエラー処理の最も単純な方法であるためです。エラーが発生した場合は停止します。