zoukankan      html  css  js  c++  java
  • [转载]使用awk进行数字计算,保留指定位小数

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

    1、bc

        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

        看似在简单计算时候完美的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

        而且…… 像一些第三方基于Linux底层的产品,为了系统本身的稳定和轻便,默认是不带bc的,例如……F5

    2、expr

        不支持浮点计算,即不支持小数,所以也常被用来判断变量内容或者结果是不是非0整数(expr 0的echo $?不是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


    3、$(())

        不支持浮点计算。

    [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")

    4、let

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

    [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
    ",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
    ",$A/$B)}'
    awk: cmd. line:1: (FILENAME=- FNR=1) fatal: division by zero attempted
    [wangdong@centos715-node1 ~]$ echo | awk "{printf ("%.2f
    ",$A/$B)}" 
    awk: cmd. line:1: {printf (%.2fn,5/16)}
    awk: cmd. line:1:          ^ syntax error
    [wangdong@centos715-node1 ~]$ echo | awk "{printf ('%.2f
    ',$A/$B)}"
    awk: cmd. line:1: {printf ('%.2f
    ',5/16)}
    awk: cmd. line:1:          ^ invalid char ''' in expression
    awk: cmd. line:1: {printf ('%.2f
    ',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
    ",$1*$2/$3-$4)}'
    -3.24
    [wangdong@centos715-node1 ~]$ echo "$A $B $C $D" | awk '{printf ("%.2f
    ",$1/$4)}'      
    0.83
    [wangdong@centos715-node1 ~]$ echo "$A $B $C $D" | awk '{printf ("%.3f
    ",$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
    ",$1)}'
    689230000
  • 相关阅读:
    Java实现 蓝桥杯VIP 算法提高 排队打水问题
    Java实现 蓝桥杯VIP 算法提高 排队打水问题
    Java实现 蓝桥杯VIP 算法提高 排队打水问题
    Java实现 蓝桥杯VIP 算法提高 特殊的质数肋骨
    Java实现 蓝桥杯VIP 算法提高 特殊的质数肋骨
    Java实现 蓝桥杯VIP 算法提高 特殊的质数肋骨
    Java实现 蓝桥杯VIP 算法提高 特殊的质数肋骨
    现在使用控件, 更喜欢继承(覆盖控件已有的函数,很奇怪的一种使用方式)
    Controls 属性与继承 TShape 类的小练习(使用TShape可以解决很多图形问题)
    QT创建窗口程序、消息循环和WinMain函数(为主线程建立了一个QEventLoop,并执行exec函数)
  • 原文地址:https://www.cnblogs.com/conanwang/p/5841764.html
Copyright © 2011-2022 走看看