web-dev-qa-db-ja.com

整数の比較:算術式または条件式

Bashでは、2つの整数を条件式を使用して比較できます

arg1 OP arg2

OPは、-eq-ne-lt-le-gt、または-geのいずれかです。これらの算術二項演算子は、arg1arg2と等しい、等しくない、以下、以下、以上、以上の場合にtrueを返します。それぞれ。 Arg1およびarg2は正または負の整数です。

または算術式:

<= >= < >の比較

== !=平等と不平等

2つの整数を比較する方法が2つあるのはなぜですか?いつ使用するのですか?

たとえば、[[ 3 -lt 2 ]]は条件式を使用し、(( 3 < 2 ))は算術式を使用します。比較が真の場合、どちらも0を返します

2つの整数を比較する場合、これら2つの方法は常に同じ意味で使用できますか?はいの場合、なぜBashには1つではなく2つのメソッドがあるのですか?

24
Tim

はい、2つの整数を比較する方法は2つあります。

これらの事実はこのフォーラムでは広く受け入れられていないようです:

  1. イディオム_[ ]_の内部では、算術比較の演算子は_-eq_、_-ne_、_-lt_、_-le_、_-gt_および_-ge_です。

    それらはテストコマンド内と_[[ ]]_内にもあるためです。

    はい、このイディオムの中では、_=_、_<_などは文字列演算子です。

  2. イディオム_(( ))_の内部では、算術比較の演算子は_==_、_!=_、_<_、_<=_、_>_、および_>=_です。 。

    いいえ、これは$(( ))のような「算術展開」(_$_で始まる)ではありません。 man bashでは「複合コマンド」として定義されています。

    はい、「算術展開」と同じ規則(内部)に従いますが、出力はなく、終了値のみが含まれます。次のように使用できます。

_if (( 2 > 1 )); then ...
_

2つの整数を比較する方法が2つあるのはなぜですか?

後者の_(( ))_は、算術テストを実行するためのより簡単な方法として開発されたと思います。 $(( ))とほとんど同じですが、出力がありません。

なぜ二人? 2つのprintf(外部および組み込み)または4つのテスト(外部test、組み込みtest、_[_および_[[_)がある理由と同じです)。これが貝殻の成長方法であり、1年間で一部の領域が改善され、翌年には他の領域が改善されます。

いつ使用するのですか?

効果的な違いはないはずなので、これは非常に難しい質問です。もちろん、_[ ]_の動作と_(( ))_の内部での動作にはいくつかの違いがありますが、2つの整数を比較する方が良いですか?誰でも!。

2つの整数を比較する場合、これら2つの方法は常に同じ意味で使用できますか?

2つの数字については、「はい」と言わざるを得ません。
しかし、変数、拡張、数学演算については、どちらか一方を支持する重要な違いがあるかもしれません。絶対に両方が等しいとは言えません。まず、_(( ))_は、いくつかの数学演算を順番に実行できます。

_if (( a=1, b=2, c=a+b*b )); then echo "$c"; fi
_

はいの場合、なぜBashには1つではなく2つのメソッドがあるのですか?

両方とも役立つ場合は、なぜでしょうか。

32
user79743

歴史的に、testコマンドは最初に存在していました(少なくとも1979年には nix Seventh Edition までさかのぼります)。演算子=!=を使用して文字列を比較し、-eq-ne-ltなどを使用して数値を比較しました。たとえば、test 0 = 00はfalseですが、test 0 -eq 00はtrueです。この構文が選択された理由はわかりませんが、シェルがリダイレクト演算子として解析した<および>を使用しないようにした可能性があります。 testコマンドは、数年後に別の構文を取得しました:[ … ]test …と同等です。

[[ … ]]条件構文は、その内部で<および>を引用符なしで演算子として使用できますが、後でkshに追加されました。 [ … ]との下位互換性を維持するため、同じ演算子を使用しましたが、文字列を比較するために<および>を追加しました(たとえば、[[ 9 > 10 ]][[ 9 -lt 10 ]]) 。詳細については、 シングルブラケットまたはダブルブラケットの使用-bash を参照してください。

算術式も、1980年代のある時点で、testコマンド Kornシェルの場合 よりも遅くなりました。彼らは、Unixのサークルで非常に人気のあったC言語の構文に従いました。したがって、彼らはCの演算子を使用しました:等しい場合は==、より小さいか等しい場合は<=など。

Unix Seventh Editionには算術式はありませんでしたが、 expr command がありました。これは、比較演算子を含む整数演算用のCのような構文も実装しました。シェルスクリプトでは、文字<および>を引用符で囲んで、シェルから保護する必要がありました。 if expr 1 \< 2; …if test 1 -lt 2; …と同等です。シェルへの算術式の追加により、exprのほとんどの使用が廃止されたため、今日ではあまり知られていません。

Shスクリプトでは、通常、算術式を使用して整数値を計算し、[ … ]を使用して整数を比較します。

if [ "$((x + y))" -lt "$z" ]; then …

Ksh、bash、またはzshスクリプトでは、両方に((…))を使用できます。

if ((x + y < z)); then …

[[ … ]]形式は、整数以外のものを含む条件を使用する場合に便利です。

テストのマニュアルページによると、=と!=は文字列比較に使用され、式-eq、-gt、-lt、-ge、-le、および-neは整数比較です。シェルスクリプトを作成するときは常にこの規則に従ってきましたが、常に機能します。式に変数がある場合は、null比較を行わないようにするために、何らかの方法で変数を引用符で囲む必要があることに注意してください。

紙の上では、あまり考えずに文字列/数値の比較を行います。一方、コンピュータは、987が数字であるか文字列であるかを認識していません。正しい結果を得るには、コンピューターに何をすべきかを伝えるためにさまざまなオペレーターが必要です。いくつかの履歴を説明する追加情報 here があります。本質的に、変数は型付けされておらず、歴史的な互換性のためにそのまま残っています。

1
signal7