web-dev-qa-db-ja.com

expr、$(())、(())の使用

シェルスクリプトでは、_expr $a*$b_を$(($a+$b))に置き換えることができます。

しかし、なぜ_(($a+$b))_だけでなく、どのリソースでも_(())_は整数計算用であると書かれているからです。

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

7
Stranger
  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
    _

*余談ですが、exprは、グロブが十分ではなく、正規表現を処理するためにPOSIXメソッドが必要な場合でも、文字列処理に役立ちます。

14
John1024

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
_
2
Steven Penny

以下のプログラムは多かれ少なかれ同じように動作し、実際には違いはないようです。しかし、それは真実ではありません。

#!/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フラグを設定する理由は、これがエラー処理の最も単純な方法であるためです。エラーが発生した場合は停止します。

0
miracle173