expr、$(())、(())

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

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

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

コメント

回答

  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メソッドが必要な場合の文字列処理に引き続き役立ちます。

コメント

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

コメントを残す

メールアドレスが公開されることはありません。 * が付いている欄は必須項目です