2017-07-31 65 views
3

我正在嘗試在bash中執行浮點算法,但由於不支持浮點數,試圖使用AWK獲取解決方案。下面是我面臨的問題:將bash表達式傳遞給AWK用於浮點算術

我看到我這個工作的罰款:

代碼

echo - | awk '{printf("%04.4f \n", (-225.2*7+30*6)/17 + (19^2)/9) }' 

輸出

-42.0301

但我的動機是「讀取表達式」,並計算正確的值爲4位小數,所以在代碼輸入相同的表達式(-225.2 * 7 + 30 * 6)/ 17 +(19^2)/ 9)其給出不正確的值(我想變量作爲字符串AWK合格):

代碼

read inpt 
echo - | awk -v input=$inpt '{printf("%04.4f \n", input) }' 

輸出

0.0000

注意:請忽略此示例表達式中第二個+的空格,以便我可以使用sed或類似的方法刪除空間(使用空格時,我會在從bash傳遞變量時在awk中獲取語法錯誤)。

任何幫助,高度讚賞。在此先感謝

聚苯乙烯:在我的情況bash版本是「bash-4.2」。我想它的bash版本阻止我使用其他選項。

+0

Bash版本不影響外部命令的可用性。訪問'bc'可能是'sudo apt install -y bc'或者您的平臺的等價物。 – tripleee

回答

0

首先,我沒有看到任何錯誤的命令,它應該工作。如果問題仍然存在,請再次嘗試發佈確切的命令並提供確切的詳細信息。

但是,如果您只需要格式化輸出,則可以直接使用printf

$ read input 
12.34 
$ printf '%4.4f' $input 
12.3400 

編輯:

如果你需要執行一些計算後格式化輸出,那麼您也可以使用bc。 (awk應該仍然工作)

$ echo "scale=4; (-225.2*7+30*6)/17+(19^2)/9" | bc 
-42.0300 

您可以表達像往常一樣使用變量,

$ read inpt 
1234 
$ echo "scale=4; $inpt * 0.01" | bc 
12.34 
+0

我實際上需要評估表達式不僅僅是打印一個浮動數字,我沒有看到在常規的bash腳本中工作。它在awk中工作,但不能將bash中的浮動表達式變量傳遞給awk構造 – PRD

+0

好吧,我說過我沒有看到你嘗試過什麼錯誤。然而,因爲我也是(如在另一個答案中)bc的粉絲,我會做一些像'echo'scale = 4;(-225.2 * 7 + 30 * 6)/ 17 +(19^2)/9「| bc'或使用'read'輸入'echo'scale = 4; $ inpt * 12.34「| bc' – Anubis

3

無法評估在AWK可變數據開箱即用。在這種情況下,您需要編寫一個算術評估器或使用預先存在的評估器,如https://github.com/radare/radare2-bindings/blob/master/awk/calc.awk。一旦你解決這個問題缺少括號和正確引用你的表情,你可以:

$ echo "((-225.2*7+30*6)/17 + (19^2)/9)" | awk -f calc.awk 
((-225.2*7+30*6)/17 + (19^2)/9) =  -42.0301 
+0

或者您可以簡單地將其設置爲'bc',同時設置所需的比例。 – Anubis

+1

在另一個答案的評論已被刪除OP提到他不能使用'bc'。 –

1

我建議,並已upvoted詹姆斯·布朗的回答。但是如果你現在需要的東西沒有外部依賴,你可以簡單地將輸入內插到腳本中。

awk "END { printf("%04.4f\n", $input) }" </dev/null 

這在功能上等同於使用eval因此,如果這不是部署在你知道你可以信任的輸入(例如,因爲它來自一個控制的過程,而不是一個實際用戶),您將需要執行一些(如果輸入不是格式良好的Awk表達式,那麼即使可能會應對奇怪或徹底誤導性的錯誤消息)。

read -p "Input an Awk expression: " input 
case $input in 
    *[!-+/*()^%0-9]*) 
    echo "$0: invalid input" >&2 
    exit 1;; 
esac 
awk ... 

還要注意避免基本沒用的構造echo。重定向來自/dev/null的輸入並將代碼放在END(或BEGIN)塊中是一種標準技術,用於在不需要任何輸入的情況下運行任意一段Awk腳本。

-1

這是你在找什麼?

echo "25 50"| awk '{print $2,"/",$1}' | bc