シェルスクリプトでは、expr $a*$b
を次のように置き換えることができます。 $(($a+$b))
。
しかし、(($a+$b))
だけではないのはなぜですか。どのリソースでも、(())
は整数計算用であると書かれているからです。
整数値の代わりに変数がある場合は、$(())
を使用しますか?また、変数が浮動小数点値を受け取ることができる場合、$(())
の代わりに何を使用する必要がありますか?
コメント
- 参照また、 unix.stackexchange.com/questions/149823/ …
回答
-
算術演算の場合、
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が古風な場合、exprテキストの代わりに何を使用すればよいですか:'。* '
-
s
がシェル変数の場合、その長さは${#s}
- $ {#}は引数の数を意味し、$(#s}は変数の文字数を意味しますか?
- はい。その'は正しいです。
- @Stranger
expr STRING : REGEX
の多くの用途はcase STRING in PATTERN)
。expr
は、正規表現がシェルワイルドカードで表現できない'場合にのみ役立ちます。
回答
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
コメント
-
expr STRING : REGEX
の多くの用途は、case STRING in PATTERN)
と書くことができます。expr
は、REGEXがシェルワイルドカードで表現できない'場合にのみ役立ちます。
回答
次のプログラムはほぼ同じように機能し、実際には違いはないようです。しかし、そうではありません。
#!/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
ここで、式はプログラムexprによって計算されます。これは、組み込みのシェルではなく、外部のUnixプログラムです。したがって、単に1とsを追加する代わりに、プログラムを開始し、その出力を読み取って変数に書き込む必要があります。プログラムを開始するには、多くのリソースと時間が必要です。そして、このプログラムは1000000回実行されます。そのため、プログラムは以前よりもはるかに遅くなります。それでも、コードは正しく機能します。
#!/bin/bash -e s=-1000 for (( i=0; i<1000000; i++ )), do ((s=s+1)) echo $s
-eフラグが設定されていない場合、プログラムも正しく機能します。ただし、-eが設定されている場合はs = -1および((s = s + 1))が計算されます。式s = s + 1は0と評価され、((0))の終了コードは> 0であり、シェルによってエラーとして解釈され、シェルはプログラムを終了します。
-eフラグを設定する理由は、エラー処理の最も簡単な方法であるためです。エラーが発生した場合は停止します。