使用awk進行數字計算,保留指定位小數

對於在Shell中進行數字的計算,其實方法有不少,可是經常使用的方法都有其弱點:node


一、bcshell

    bc應該是最經常使用的Linux中計算器了,簡單方便,支持浮點。
express

[wangdong@centos715-node1 ~]$ echo 1+2 |bc
3
[wangdong@centos715-node1 ~]$ echo 5.5*3.3 |bc
18.1
[wangdong@centos715-node1 ~]$ echo 5/3 |bc
1
[wangdong@centos715-node1 ~]$ echo "scale=2;5/3" |bc
1.66

    看似在簡單計算時候完美的bc,其實也有一個讓我抓狂的地方,固然有可能有辦法能夠解決,只是我不知道而已,那就是…… 在出現整數部分爲0的時候,這個0是不顯示出來的,例如0.5只會顯示爲.5,情何以堪!centos

[wangdong@centos715-node1 ~]$ echo "scale=2;1/2" |bc
.50
[wangdong@centos715-node1 ~]$ echo "scale=4;17/20" |bc    
.8500

    並且…… 像一些第三方基於Linux底層的產品,爲了系統自己的穩定和輕便,默認是不帶bc的,例如……F5
bash


二、expride

    不支持浮點計算,即不支持小數,因此也常被用來判斷變量內容或者結果是否是非0整數(expr 0的echo $?不是0)。centos7

[wangdong@centos715-node1 ~]$ expr 3 + 5
8
[wangdong@centos715-node1 ~]$ expr 10 / 2
5
[wangdong@centos715-node1 ~]$ expr 10 / 3
3
[wangdong@centos715-node1 ~]$ expr 7 / 2
3
[wangdong@centos715-node1 ~]$ expr 0
0
[wangdong@centos715-node1 ~]$ echo $?
1


三、$(())spa

    不支持浮點計算。
字符串

[wangdong@centos715-node1 ~]$ echo $((8+3))
11
[wangdong@centos715-node1 ~]$ echo $((10/2))
5
[wangdong@centos715-node1 ~]$ echo $((10/3))
3
[wangdong@centos715-node1 ~]$ echo $((1.5*3))
-bash: 1.5*3: 語法錯誤: 無效的算術運算符 (錯誤符號是 ".5*3")


四、let
cmd

    不只不支持浮點計算,並且還只能賦值,不能直接輸出。

[wangdong@centos715-node1 ~]$ let a=1+2
[wangdong@centos715-node1 ~]$ echo $a
3
[wangdong@centos715-node1 ~]$ let b=10/5
[wangdong@centos715-node1 ~]$ echo $b
2
[wangdong@centos715-node1 ~]$ let c=1.5*3
-bash: let: c=1.5*3: 語法錯誤: 無效的算術運算符 (錯誤符號是 ".5*3")
[wangdong@centos715-node1 ~]$ echo $c
[wangdong@centos715-node1 ~]$


上面的幾種方式,是我以前經常使用的方式,可是如今我在shell腳本中有一個需求,在計算數字時,會出現浮點計算,也會出現0-1之間的小數,前面的幾個方式恐怕都沒法知足。


    這裏,我使用的是awk計算:

[wangdong@centos715-node1 ~]$ echo | awk '{print 17/20}'
0.85
[wangdong@centos715-node1 ~]$ echo | awk '{print 1.5*3}'
4.5

    看上去還能夠,那麼進一步,我須要帶變量:

[wangdong@centos715-node1 ~]$ A=5
[wangdong@centos715-node1 ~]$ B=16
[wangdong@centos715-node1 ~]$ C=29
[wangdong@centos715-node1 ~]$ echo | awk '{print $A/$B}'
awk: cmd. line:1: (FILENAME=- FNR=1) fatal: division by zero attempted
[wangdong@centos715-node1 ~]$ echo | awk "{print $A/$B}" 
0.3125
[wangdong@centos715-node1 ~]$ echo | awk "{print $C*$A}"
145
[wangdong@centos715-node1 ~]$ echo | awk "{print $C*$A/$B}"
9.0625

    看上去也還能夠,只是注意awk後的單引號須要變爲雙引號。

    再進一步,上面最後一次的計算,小數點後面出現了4位,我但願只保留兩位,否則看着太亂。可是沒有找到這裏能夠保留小數位的參數和方法,因而我嘗試一下將print換爲printf:

[wangdong@centos715-node1 ~]$ echo | awk '{print 10/3}'
3.33333
[wangdong@centos715-node1 ~]$ echo | awk '{printf ("%.2f\n",10/3)}' 
3.33

    將print換成printf,就能夠有方法進行小數位的限制了,看似不錯,可是……

[wangdong@centos715-node1 ~]$ A=5
[wangdong@centos715-node1 ~]$ B=16
[wangdong@centos715-node1 ~]$ C=29
[wangdong@centos715-node1 ~]$ echo | awk '{printf ("%.2f\n",$A/$B)}'
awk: cmd. line:1: (FILENAME=- FNR=1) fatal: division by zero attempted
[wangdong@centos715-node1 ~]$ echo | awk "{printf ("%.2f\n",$A/$B)}" 
awk: cmd. line:1: {printf (%.2fn,5/16)}
awk: cmd. line:1:          ^ syntax error
[wangdong@centos715-node1 ~]$ echo | awk "{printf ('%.2f\n',$A/$B)}"
awk: cmd. line:1: {printf ('%.2f\n',5/16)}
awk: cmd. line:1:          ^ invalid char ''' in expression
awk: cmd. line:1: {printf ('%.2f\n',5/16)}
awk: cmd. line:1:          ^ syntax error

    使用變量參與計算的話,會發現一直在報錯,這種狀況,建議先在前面的echo中將須要使用的變量輸出出來,再進行調用。

[wangdong@centos715-node1 ~]$ A=5
[wangdong@centos715-node1 ~]$ B=16
[wangdong@centos715-node1 ~]$ C=29
[wangdong@centos715-node1 ~]$ D=6
[wangdong@centos715-node1 ~]$ echo "$A $B $C $D" | awk '{printf ("%.2f\n",$1*$2/$3-$4)}'
-3.24
[wangdong@centos715-node1 ~]$ echo "$A $B $C $D" | awk '{printf ("%.2f\n",$1/$4)}'      
0.83
[wangdong@centos715-node1 ~]$ echo "$A $B $C $D" | awk '{printf ("%.3f\n",$1/$4)}'
0.833

    注意,使用printf的時候,awk後面必須是單引號,雙引號會報錯。雖然這種方法麻煩一些,可是起碼能夠實現個人需求,若是有朋友知道bc計算的結果爲0-1之間的小數時,怎麼讓他顯示出來前面的0. ,歡迎留言,不喜勿噴。


    補充,有的時候在計算數字後,會發現你的結果已經不是正常的一串數字了,而是在其中穿插了字母e或者E,這是由於數字過大,系統採用了相似於科學計數法的表達方式(正確叫法不肯定,勿噴),可是若是直接使用這一串內容再去計算的話,會報錯,系統會認爲這是字符串而非數字,這種狀況也可使用awk進行轉變,其實準確的說是printf的功能。

[wangdong@centos715-node1 uncomp]$ echo "6.8923e+08/100" |bc
(standard_in) 1: syntax error
[wangdong@centos715-node1 uncomp]$ echo "6.8923e+08" | awk '{printf ("%.0f\n",$1)}'
689230000
相關文章
相關標籤/搜索