对于在Shell中进行数字的计算,其实方法有很多,但是常用的方法都有其弱点:

    1、bc

    1. bc应该是最常用的Linux中计算器了,简单方便,支持浮点。

    [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
    1.
    2.
    3.
    4.
    5.
    6.
    7.
    8.
    看似在简单计算时候完美的bc,其实也有一个让我抓狂的地方,当然有可能有办法可以解决,只是我不知道而已,那就是…… 在出现整数部分为0的时候,这个0是不显示出来的,例如0.5只会显示为.5,情何以堪!

    [wangdong@centos715-node1 ~]$ echo “scale=2;1/2” |bc
    .50
    [wangdong@centos715-node1 ~]$ echo “scale=4;17/20” |bc
    .8500
    1.
    2.
    3.
    4.
    而且…… 像一些第三方基于Linux底层的产品,为了系统本身的稳定和轻便,默认是不带bc的,例如……F5

    2、expr

    1. 不支持浮点计算,即不支持小数,所以也常被用来判断变量内容或者结果是不是非0整数(expr 0echo $?不是0)。

    [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
    1.
    2.
    3.
    4.
    5.
    6.
    7.
    8.
    9.
    10.
    11.
    12.

    3、$(())

    1. 不支持浮点计算。

    [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.53))
    -bash: 1.5
    3: 语法错误: 无效的算术运算符 (错误符号是 “.5*3”)
    1.
    2.
    3.
    4.
    5.
    6.
    7.
    8.

    4、let

    1. 不仅不支持浮点计算,而且还只能赋值,不能直接输出。

    [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.53
    -bash: let: c=1.5
    3: 语法错误: 无效的算术运算符 (错误符号是 “.5*3”)
    [wangdong@centos715-node1 ~]$ echo $c
    [wangdong@centos715-node1 ~]$
    1.
    2.
    3.
    4.
    5.
    6.
    7.
    8.
    9.
    10.

    上面的几种方式,是我之前常用的方式,但是现在我在shell脚本中有一个需求,在计算数字时,会出现浮点计算,也会出现0-1之间的小数,前面的几个方式恐怕都无法满足。

    1. 这里,我使用的是awk计算:

    [wangdong@centos715-node1 ~]$ echo | awk ‘{print 17/20}’
    0.85
    [wangdong@centos715-node1 ~]$ echo | awk ‘{print 1.5*3}’
    4.5
    1.
    2.
    3.
    4.
    看上去还可以,那么进一步,我需要带变量:

    [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
    1.
    2.
    3.
    4.
    5.
    6.
    7.
    8.
    9.
    10.
    11.
    看上去也还可以,只是注意awk后的单引号需要变为双引号。

    1. 再进一步,上面最后一次的计算,小数点后面出现了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
    1.
    2.
    3.
    4.
    将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
    1.
    2.
    3.
    4.
    5.
    6.
    7.
    8.
    9.
    10.
    11.
    12.
    13.
    使用变量参与计算的话,会发现一直在报错,这种情况,建议先在前面的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
    1.
    2.
    3.
    4.
    5.
    6.
    7.
    8.
    9.
    10.
    注意,使用printf的时候,awk后面必须是单引号,双引号会报错。虽然这种方法麻烦一些,但是起码可以实现我的需求,如果有朋友知道bc计算的结果为0-1之间的小数时,怎么让他显示出来前面的0. ,欢迎留言,不喜勿喷。

    1. 补充,有的时候在计算数字后,会发现你的结果已经不是正常的一串数字了,而是在其中穿插了字母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
    1.
    2.
    3.
    4.

    —————————————————-
    ©著作权归作者所有:来自51CTO博客作者radish1027的原创作品,请联系作者获取转载授权,否则将追究法律责任
    使用awk进行数字计算,保留指定位小数
    https://blog.51cto.com/radish/1736900