expr、$(())、(())を使う

expr、$(())、(())を使う

シェルスクリプトではexpr $a*$b$(($a+$b))

(($a+$b))ただし、すべてのリソースで(())整数の計算に使用されるため、使用しないことをお勧めします。

それでは、$(())変数があるときに整数値の代わりに何を使うべきですか?$(())変数が浮動小数点値を受け取ることができる場合は、代わりに何を使用する必要がありますか?

答え1

  1. 算術の場合、exprこれは古代です。使用しないでください。 *

  2. $((...))そして((...))非常に似ています。両方とも整数計算のみを実行します。違いは、$((...))計算結果を返し、((...))計算結果を返さないことです。$((...))文に非常に便利ですecho

     $ a=2; b=3; echo "$((a*b))"
     6
    

    ((...))変数を割り当てたり終了コードを設定したりする場合に便利です。

     $ a=3; b=3; ((a==b)) && echo yes
     yes
    
  3. 浮動小数点の計算が必要な場合、bcまたは以下を使用しますawk

    $ echo '4.7/3.14' | bc -l
    1.49681528662420382165
    
    $ awk 'BEGIN{print 4.7/3.14}'
    1.49682
    

*BTW、exprglobは、globが不十分で正規表現にPOSIXメソッドが必要な場合に文字列を処理するのにまだ役立ちます。

答え2

exprは古いですが、使用は限られていると思います。文字列を検索するとしましょう。 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

答え3

次のプログラムはほとんど同じことを行い、実際の違いはないようです。しかしそれは真実ではない。

#!/bin/bash 
s=-1000
for (( i=0; i<1000000; i++ )); do
    s=$((s+1))
done
echo "$s"

これが正しい方法です。 s + 1式はシェルによって評価され、変数に割り当てることができます。

#!/bin/bash
s=-1000
for (( i=0; i<1000000; i++ )); do
    s=`expr "$s" + 1`
done
echo "$s"

ここの式は、組み込みシェルではなく外部Unixプログラムであるexprプログラムによって評価されます。したがって、単に1を足すことはできず、saプログラムを起動し、対応する出力を読み取り、変数に書き込む必要があります。プロジェクトを開始するには多くのリソースと時間が必要です。そして、このプログラムは1,000,000回実行されました。したがって、プログラムは以前よりはるかに遅くなります。それでもコードはうまくいきます。

#!/bin/bash -e
s=-1000
for (( i=0; i<1000000; i++ )); do
    ((s=s+1))
done
echo "$s"

-e フラグが設定されていない場合でも、プログラムは正常に動作します。ただし、s = -1のときに-eを設定すると((s = s + 1))が計算されます。 s = s + 1式は0と評価され((0))、終了コード> 0があり、これはシェルでエラーとして解釈され、シェルはプログラムを終了します。

-eフラグを設定する理由は、エラーを処理する最も簡単な方法です。エラーが発生した場合は停止します。

関連情報