
今朝、bash で 2 つの 10 進数を比較する方法について検索したところ、次の回答にたどり着きました。シェルスクリプトで浮動小数点数と比較する方法ただし、これには含まれませんこの答えはここにあります:
$ [[ ((3.56 < 2.90)) ]]; echo $?
1
$ [[ ((3.56 < 4.90)) ]]; echo $?
0
その回答が低評価されていること、そしてそれがある種の異常なバシズムのように見えることを考慮すると、この算術評価は正確性に関して信頼できるのでしょうか?
答え1
bash
浮動小数点数を理解しません。マニュアルページのセクション
を引用しますbash
算術評価:
評価は固定幅の整数で行われます[…]。
したがって、((3 < 4))
または は((3 < 2))
実際に正しい算術式です。次のように入力できます。
$ echo "$((3 < 4)) -- $((3 < 2))"
出力:
1 -- 0
ただし、$ echo $((3.3 < 3.6))
構文エラー メッセージが返されます。例では、実際に文字列を比較しています。したがって、次の例をご覧ください。
$ [[ ((3.56 < 04.90)) ]]; echo $?
出力:
1
答え2
内部は[[...]]
<
文字列比較用です。
したがって[[ 3.56 < 2.90 ]]
、 or[[ (3.56 < 2.90) ]]
または[[ ((3.56 < 2.90)) ]]
or ... は、文字列を単に語彙的に文字列と[[ (((3.56 < 2.90))) ]]
比較するだけです(語彙的には、たとえばより大きいです)。3.56
2.90
3
10
整数の比較の場合は、[[ 3 -lt 2 ]]
またはです(( 3 < 2 ))
。浮動小数点の比較が必要な場合は、ksh93
、zsh
または、またはyash
のような外部ユーティリティが必要です。これは実行できません。awk
perl
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
コードとして解釈され、たとえばawk
それを使用してコマンドを実行できますsystem()
)。