对于在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\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

[转载]使用awk进行数字计算,保留指定位小数的更多相关文章

  1. layui table 前台数字格式保留两位小数,不足补0(mysql 数据库)

    layui table 对于后台json数据,有数字的,默认不会原样显示,而是只取数值,即100.00显示为100.如果想原样显示,需转为字符串. 项目采用mysql数据库,字段类型为decimal( ...

  2. Loadrunner 计算保留两位小数不四舍五入

    有时候在测试过程中会截取返回值,当你截取的值不是最终的值,需要进行计算后才能使用并且需要保留两位小数,不进行四舍五入的计算: 此时 我使用了各种办法,但是最终我采用了一种最直接,最暴力的方法就是先乘后 ...

  3. UITextField 文本框 只能输入数字 且保留2位小数 实现

    http://blog.sina.com.cn/s/blog_aa7579f601015xvx.html #pragma mark - #pragma mark UITextField - (BOOL ...

  4. JS中移除非数字,最多保留一位小数

    //去除非数字 var clearNoNum = function (item) { if (item!=null && item!=undefined) { //先把非数字的都替换掉 ...

  5. vue input框数字后保留两位小数正则

    <el-input type="text" v-model.trim="ruleForm2.marketPrice" maxlength="10 ...

  6. td内的所有数字格式化保留两位小数

    $("td").each(function(i,el){ var td = parseFloat($(el).text()); if(!isNaN(td)){ $(el).text ...

  7. java读写文件及保留指定位小数

    1)先上代码: public static void main(String[] args)throws IOException{ double[][] B=new double[1043][2102 ...

  8. (Math.round(num*100)/100).toFixed(2); 将输入的数字变成保留两位小数

    <input type="number" @input="onInputPrice" @blur="onPrice" data-id= ...

  9. js保留两位小数的数字格式化方法

    // 格式化数字(保留两位小数) numberFormat (num) { let percent = Number(num.toString().match(/^\d+(?:\.\d{0,2})?/ ...

随机推荐

  1. SAP ABAP编程 Table Control动态隐藏列

    在SAP DIALOG设计中,有时候须要动态的隐藏某些列,以下是方法. ***数据定义 CONTROLS: table_control TYPE TABLEVIEW USING SCREEN 0100 ...

  2. jmeter的安装

        1.安装jdk和环境变量配置 变量名:[JAVA_HOME] 变量值:[D:\Program Files\Java\jdk1.8.0_92][jdk安装路径] 变量名:[path] 变量值:[ ...

  3. Python爬虫(二十二)_selenium案例:模拟登陆豆瓣

    本篇博客主要用于介绍如何使用selenium+phantomJS模拟登陆豆瓣,没有考虑验证码的问题,更多内容,请参考:Python学习指南 #-*- coding:utf-8 -*- from sel ...

  4. Intellij IDEA 4种配置热部署的方法

    热部署可以使的修改代码后,无须重启服务器,就可以加载更改的代码. 第1种:修改服务器配置,使得IDEA窗口失去焦点时,更新类和资源 菜单Run -> EditConfiguration , 然后 ...

  5. intellij 打开node项目 一直停留在scanning files to index....,或跳出内存不够的提示框

    说明: 在npm install 后,会出现Scanning files to index ...... 出现这个是正常的,但是一直不消失就不正常了.原因是npm install 后 node_mod ...

  6. 解决iOS手势冲突问题

    今天在做一个效果的时候,由于子视图和父视图都有响应的事件,子视图的事件理所当然被父视图拦截掉了,接下来就做分析解决 1.  tableviewcell可以触发点击,同时tableview的父视图有点击 ...

  7. gearman学习笔记1

    1.简介       gearman是一个分布式开发框架,适合处理一些必须处理但是不影响主流程的操作,比如保存日志.发送邮件.缩略图片等.最早是基于perl语言的,2008年发布的时候改为C++语言开 ...

  8. shell if相关参数

    [ -a FILE ] 如果 FILE 存在则为真. [ -b FILE ] 如果 FILE 存在且是一个块特殊文件则为真. [ -c FILE ] 如果 FILE 存在且是一个字特殊文件则为真. [ ...

  9. alias 命令详解

    alias 命令 作用:  设置命令别名,可以将较长的命令进行简化,使用alias 时,用户必须使用单引号将原来的命令引起来,防止特殊字符导致错误. 如要永久生效则将alias 命令存放到bash 的 ...

  10. Apache Avro# 1.8.2 Specification (Avro 1.8.2规范)一

    h4 { text-indent: 0.71cm; margin-top: 0.49cm; margin-bottom: 0.51cm; direction: ltr; color: #000000; ...