Bash での算術演算

算術式

((...)) 構文は、整数に対して算術演算を実行できます。

$ ((foo = 5 + 5))
$ echo $foo
10

((...)) は内部スペースを自動的に無視するため、以下の記述方法は正しく、同じ結果が得られます。

$ ((2+2))
$ (( 2+2 ))
$ (( 2 + 2 ))

この構文は値を返しません。コマンドの実行結果は算術演算の結果によって決まります。演算結果が「0」でない限り、コマンドは正常に実行されます。

$ (( 3 + 2 ))
$ echo $?
0

上の例では、「3 + 2」の結果は 5 です。コマンドが正常に実行された場合でも、環境変数「$?」は「0」です。

算術結果が「0」の場合、コマンドは失敗します。

$ (( 3 - 3 ))
$ echo $?
1

上記の例では、「3 - 3」の結果は「0」、環境変数「$?」は「1」となり、コマンドの実行が失敗したことを示しています。

算術演算の結果を読みたい場合は、「((...))」の前にドル記号「$((...))」を追加して算術式に変換して返す必要があります。算術演算の値。

$ echo $((2 + 2))
4

((...)) 構文でサポートされる算術演算子は次のとおりです。

  • +: 追加
  • -: 減算
  • *: 乗算
  • /: 除算(割り算可能)
  • %: 余り
  • **: インデックス
  • ++: インクリメント演算 (プレフィックスまたはサフィックス)
  • --: デクリメント演算 (プレフィックスまたはサフィックス)

たとえば、「5」を「2」で割った場合、結果は「2.5」ではなく「2」になることに注意してください。

$ echo $((5 / 2))
2

2 つの演算子 ++-- には接頭辞と接尾辞があります。接頭辞の場合、最初に操作が実行されてから値が返されます。接尾辞の場合、最初に値が返されてから操作が実行されます。

$ i=0
$ echo $i
0
$ echo $((i++))
0
$ echo $i
1
$ echo $((++i))
2
$ echo $i
2

上の例では、サフィックスとして ++ を指定すると、最初に値が返され、echo コマンドが実行され、次にプレフィックスとして自動インクリメント操作が実行され、次に値が返されます。そして「echo」コマンドを実行します。

$((...)) 内で括弧を使用すると、演算の順序を変更できます。

$ echo $(( (2 + 3) * 4 ))
20

上記の例では、内側の括弧により、乗算の前に加算が実行されます。

$((...)) 構造はネストできます。

$ echo $(((5**2) * 3))
75
$ echo $(($((5**2)) * 3)) # に相当
75

この構文は整数のみを計算できます。それ以外の場合はエラーが報告されます。

# エラーを報告する
$ echo $((1.5 + 1))
bash: 構文エラー

$((...)) の括弧内では、変数名の前に $ を追加する必要はありませんが、追加してもエラーは報告されません。

$ number=2
$ echo $(($number + 1))
3

上記の例では、変数番号の前にドル記号があってもなくても、結果は同じです。

$((...)) 内で文字列を使用すると、Bash はそれを変数名とみなします。同じ名前の変数が存在しない場合、Bash はそれを null 値として扱うため、エラーは報告されません。

$ echo $(( "hello" + 2))
2
$ echo $(( "hello" * 2))
0

上の例では、"hello" は変数名とみなされ null 値が返されますが、$((...)) は null 値を 0 として扱うため、次の結果が返されます。乗算は 0 です。同様に、$((...))に存在しない変数を使用した場合も0として扱われます。

変数の値が文字列の場合、処理ロジックは上記と同じです。つまり、文字列が既存の変数に対応しない場合、$((...)) では null 値として扱われます。

$ foo=hello
$ echo $(( foo + 2))
2

上記の例では、変数 foo の値は hello であり、hello も変数名とみなされます。これにより、動的に置き換えられるコードを書くことが可能になります。

$ foo=hello
$ hello=3
$ echo $(( foo + 2 ))
5

上記のコードでは、foo + 2 は変数 hello の値に依存します。

最後に、$[...] は以前の構文ですが、整数演算にも使用できますが、お勧めできません。

$ echo $[2+2]
4

数値の底

Bash の値はデフォルトでは 10 進数ですが、算術式では他の基数も使用できます。

  • number: 特別な表現のない数値は 10 進数 (基数 10) です。
  • 0number: 8 進数。
  • 0xnumber: 16 進数。
  • base#number: base の基本番号。

以下にいくつかの例を示します。

$ echo $((0xff))
255
$ echo $((2#11111111))
255

上面例子中,0xff是十六进制数,2#11111111是二进制数。

ビット演算

$((...)) は次の 2 進ビット演算子をサポートします。

  • <<: ビット左シフト演算。数値のすべてのビットを指定されたビットだけ左に移動します。
  • >>: ビット右シフト演算。数値のすべてのビットを指定されたビットだけ右に移動します。
  • &: ビットごとの AND 演算。2 つの数値のすべてのビットに対して AND 演算を実行します。
  • |: ビットごとの OR 演算。2 つの数値のすべてのビットに対して OR 演算を実行します。
  • ~: ビットごとの「いいえ」演算。数値のすべてのビットを反転します。
  • ^: ビット単位の排他的 OR 演算 (排他的論理和)。2 つの数値のすべてのビットに対して排他的 OR 演算を実行します。

以下は右シフト演算子「>>」の例です。

$ echo $((16>>2))
4

以下は左シフト演算子「<<」の例です。

$ echo $((16<<2))
64

以下は、「17」 (バイナリ「10001」) と「3」 (バイナリ「11」) に対するさまざまなバイナリ演算の結果です。

$ echo $((17&3))
1
$ echo $((17|3))
19
$ echo $((17^3))
18

論理演算

$((...)) は次の論理演算子をサポートします。

  • <: より小さい
  • >: より大きい
  • <=: 以下
  • >=: 以上
  • ==: 等しい
  • !=: 等しくない
  • &&: 論理積
  • ||: 論理和
  • !: 論理いいえ
  • expr1?expr2:expr3: 三項条件演算子。式 expr1 がゼロ以外の値 (算術 true) に評価された場合は、式 expr2 が実行され、それ以外の場合は式 expr3 が実行されます。

論理式が真の場合は「1」を返し、それ以外の場合は「0」を返します。

$ echo $((3 > 2))
1
$ echo $(( (3 > 2) || (4 <= 1) ))
1

三項演算子は、単一の論理テストを実行します。これは「if/then/else」ステートメントのように機能します。

$ a=0
$ echo $((a<1 ? 1 : 0))
1
$ echo $((a>1 ? 1 : 0))
0

上の例では、最初の式が true の場合は 2 番目の式の値が返され、それ以外の場合は 3 番目の式の値が返されます。

代入演算

算術式 $((...)) は代入演算を実行できます。

$ echo $((a=1))
1
$ echo $a
1

上の例では、「a=1」は変数「a」に値を代入します。この数式自体も式であり、戻り値は等号の右側の値になります。

$((...)) でサポートされる代入演算子には次のものがあります。

  • parameter = value:単純な割り当て。
  • parameter += valueparameter = parameter + value
  • parameter -= valueparameter = parameter – valueに相当。
  • parameter *= valueparameter = parameter * valueに相当。
  • parameter /= valueparameter = parameter / valueに相当。
  • parameter %= valueparameter = parameter % valueに相当。
  • parameter <<= valueparameter = parameter << valueに相当。
  • parameter >>= valueparameter = parameter >> valueに相当。
  • parameter &= valueparameter = parameter & valueに相当。
  • parameter |= valueparameter = parameter | valueに相当。
  • parameter ^= valueparameter = parameter ^ valueに相当。

以下に例を示します。

$ foo=5
$ echo $((foo*=2))
10

式内で値を割り当てる場合は、括弧で囲むことができます。そうしないと、エラーが報告されます。

$ echo $(( a<1 ? (a+=1) : (a-=1) ))

評価操作

$((...)) 内のコンマ , は評価演算子で、前後 2 つの式を実行し、後者の式の値を返します。

$ echo $((foo = 1 + 2, 3 * 4))
12
$ echo $foo
3

上記の例では、カンマの前後の両方の式が実行され、後者の式 12 の値が返されます。

expr コマンド

expr コマンドは算術演算をサポートしており、((...)) 構文を使用する必要はありません。

$ expr 3 + 2
5

expr コマンドは変数置換をサポートしています。

$ foo=3
$ expr $foo + 2
5

expr コマンドも非整数の引数をサポートしません。

$ expr 3.5 + 2
expr: 非整数参数

上記の例では、非整数演算がある場合、expr コマンドはエラーを報告します。

let コマンド

「let」コマンドは、算術演算の結果を変数に代入するために使用されます。

$ let x=2+3
$ echo $x
5

上の例では、変数 x2+3 の結果と等しくなります。

数式「x=2+3」にはスペースを含めることはできません。スペースを含めるとエラーが報告されます。 「let」コマンドの詳細な使用法については、「変数」の章を参照してください。


作者: wangdoc

アドレス: https://wangdoc.com/

ライセンス: クリエイティブ・コモンズ 3.0