2013-03-05 37 views
23

我想將浮點變量與整數進行比較。 我知道這不是最好的與bash,但我的整個腳本已經寫在bash中。 $ number可以是任何整數。如果它低於或等於50,我想要output1,對於其他所有其他我想用另一個變量k輸出。這是我到目前爲止:與bash中的變量進行浮點比較

number=43 
test=$(echo "scale=2; $number/50" | bc -l) 
echo "$test" 
for k in {1..5} 
do 
    if ["$test" -le 1] 
    then echo "output" 

    elif ["$test" -gt $k] 
    then echo "output$k" 
    fi 
done 

如果我嘗試與測試= 0.43,第一個循環甚至不工作。我認爲它與整數和浮點比較有關,但不能使其工作。

我失蹤了嗎?

PS:此[0.43: command not found是終端輸出。

+0

你也可以切換到KSH和使用排版,自動輪。 (這是自1993年以來可用,運作良好) – 2016-09-20 01:04:35

回答

43

Bash無法處理浮游物。管bc代替:

if [ $(echo " $test > $k" | bc) -eq 1 ] 

看到,雖然該錯誤是因爲test命令(即[)前後

它甚至更好,因爲你比較喜歡這個號碼使用((...))需求空間:

if (($(bc <<< "$test > $k"))) 

在循環中的部分應該是這樣的:

if (($(bc <<< "$test <= 1"))) 
then 
    echo "output" 
elif (($(bc <<< "$test > $k"))) 
then 
    echo "output$k" 
fi 

如果關係爲假,則關係表達式求值爲0;如果關係爲真,則關係表達式求值爲1 [source]。請注意,這是GNU bc的行爲,並不是POSIX compiant。

+1

此外:bash:[:1.3:預期的整數表達式將是錯誤,如果您已正確格式化[]表達式。 + 1 @ user000001 – 2013-03-05 13:18:51

+0

非常感謝!有用。小問題,我正在努力研究。我想第一個要麼小於或等於1,要麼其他要嚴格高於k。我可以寫(($(bc <<<「$ test <1」&&「$ test = 1」)== 1))或(($(bc <<<「$ test <= 1」)== 1) ))? – user1983400 2013-03-05 15:43:08

+0

第二個是正確的。第一個是正確的,你引用像這樣:'(($(bc <<<「$ test <1 && $ test == 1」)== 1))'(也是'==')。有關'bc'中布爾表達式的更多信息,請參見:http://www.gnu.org/software/bc/manual/html_mono/bc.html#SEC12 – user000001 2013-03-05 15:52:15

9

這是一個古老的問題,但它帶有一個額外的答案,我認爲。

雖然管道連接到更高精度的計算器(bc或dc)可以工作,但這是以fork和額外的過程爲代價的,因爲這些計算器不是內置到bash中的。但是,內置的一件事是printf。所以,如果你能處理你的號碼是小數的具體數量範圍內,可以通過「假」浮點比較,具有這樣的功能:

#!/usr/bin/env bash 

function [[[() { 
    local LANG=C lhs rhs 
    printf -v lhs '%07.3f' "$1"; lhs=${lhs/./} 
    printf -v rhs '%07.3f' "$3"; rhs=${rhs/./} 
    case "$2" in 
    -lt) return $((! (10#$lhs < 10#$rhs))) ;; 
    -le) return $((! (10#$lhs <= 10#$rhs))) ;; 
    -eq) return $((! (10#$lhs == 10#$rhs))) ;; 
    -ge) return $((! (10#$lhs >= 10#$rhs))) ;; 
    -gt) return $((! (10#$lhs > 10#$rhs))) ;; 
    esac 
} 

number=${1:-43} 
test=$(dc -e "2k $number 50/p") 
echo "$test" 

for k in {1..5}; do 
    if [[[ "$test" -le 1 ]]]; then 
     echo "output" 
    elif [[[ "$test" -gt "$k" ]]]; then 
     echo "output $k" 
    fi 
done 

幾件事情需要考慮。

  • 我已經命名功能[[[是可愛的。你可以隨便命名。 ntestmynumericcomparison或甚至[[[
  • printf是bash中的一個內部函數,所以儘管它在你的路徑上,但它並不會花費一個分支。
  • 就目前而言,該功能支持最高999.999的數字。如果您需要更高的數字(或更高精度),請調整printf格式。
  • case聲明中每個變量開始處的10#強制比較發生在基數10,因爲零填充的數字可能會被解釋爲八進制數。

參見:http://mywiki.wooledge.org/BashFAQ/022

+1

這看起來相當不錯,但爲了複製粘貼,我將'printf'格式設置爲更明智的選項(漂浮可能很長,並且保持低精度不會使此函數更快)。 – 2016-01-12 08:05:34