web-dev-qa-db-ja.com

bashでの10進数の比較

今朝の私の検索は、bashで2つの10進数を比較する方法についてでした。私はこの答えに行きました: シェルスクリプトで浮動小数点数と比較する方法 。ただし、これには この回答は含まれていません

$ [[ ((3.56 < 2.90)) ]]; echo $?
1
$ [[ ((3.56 < 4.90)) ]]; echo $?
0

その回答が反対投票されており、ある種の異常なバシズムに見えることを考えると、この算術評価は正確性について信頼できるのでしょうか?

7
Teresa e Junior

bashは浮動小数点数を認識しません。
引用bashマニュアルページ、セクションARITHMETIC EVALUATION

評価は固定幅整数[…]で行われます。

したがって、_((3 < 4))_または_((3 < 2))_は実際には正しい算術式です。次のように入力できます。

_$ echo "$((3 < 4)) -- $((3 < 2))"
_

出力:_1 -- 0_

ただし、$ echo $((3.3 < 3.6))は構文エラーメッセージを返します。あなたの例では、実際には文字列を比較しています。したがって、いくつかの例:

_$ [[ ((3.56 < 04.90)) ]]; echo $?
_

出力:_1_

12
Qeole

_[[...]]_の内部_<_は文字列比較用です。

つまり、_[[ 3.56 < 2.90 ]]_または[[ (3.56 < 2.90) ]]または[[ ((3.56 < 2.90)) ]]または[[ (((3.56 < 2.90))) ]] ...は、_3.56_文字列を_2.90_文字列と字句的に比較しているだけです(そして、字句的には、_3_は_10_よりも大きいです)。

整数比較の場合、これは_[[ 3 -lt 2 ]]_または_(( 3 < 2 ))_です。浮動小数点比較が必要な場合は、_ksh93_、zshまたはyashまたはawkPerlなどの外部ユーティリティが必要です。 bashはできません。

たとえば、次のような関数を定義できます。

_compare() (IFS=" "
  exec awk "BEGIN{if (!($*)) exit(1)}"
)
_

たとえば、次のように使用できます。

_if compare '1.5*10 < 1e3'; then
  echo less
fi
_

またはそのことについてさえ:

_if compare '"bar" < "foo"'...
_

文字列比較を行います。

コマンドインジェクションの脆弱性を構成するため、制御されていない外部から提供されたデータをcompare関数に渡さないでください(データはawkコードとして解釈され、awksystem()など)。

11