
今天早上我的搜尋是關於如何在 bash 中比較兩個十進制數,我得到了這個答案:如何在 shell 腳本中與浮點數進行比較。然而,這項一項不包括這個答案在這裡:
$ [[ ((3.56 < 2.90)) ]]; echo $?
1
$ [[ ((3.56 < 4.90)) ]]; echo $?
0
考慮到這個答案已被否決,而且看起來有些不尋常的羞辱,這個算術評估的準確性是否值得信賴?
答案1
bash
不懂浮點數。
引用bash
手冊頁,部分算術評估:
評估以固定寬度整數完成[...]。
所以((3 < 4))
or((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 or [[ (3.56 < 2.90) ]]
or [[ ((3.56 < 2.90)) ]]
or [[ (((3.56 < 2.90))) ]]
... 只是將3.56
字串與2.90
詞法上的字串進行比較(詞法上,例如3
大於)。10
對於整數比較,它是[[ 3 -lt 2 ]]
or (( 3 < 2 ))
。如果您想要浮點比較,您需要ksh93
,zsh
或yash
外部實用程序,例如awk
or 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()