Shell之数学计算
本博客已经迁往http://www.kemaswill.com/, 博客园这边也会继续更新, 欢迎关注~
数学计算是Shell中比较常用的一种操作, 但是因为shell中所有的变量都默认为字符串, 这就使得在shell中进行数学计算比较复杂, 以下直觉上貌似正确的方法是不对的:
#第一种错误方法 $ var=1+1 #第二种错误方法 $ var=1 $ var=$var+1
以上两种方法的输出结果都是1+1 , 而不是我们期望的2 .
在shell中进行数学计算可以通过以下方法来进行:
1. declare
我们可以声明一个变量的类型, 比如声明变量n为整数declare -i n
$ n=6/3 $ echo $n 6/3 $ declare -i n $ n=6/3 $ echo $n 2
2. expr
可以使用expr命令, 注意其对空格比较敏感, 需要在+号附近都有空格
$ z=5 $ z=`expr $z+1` ---- Need spaces around + sign. $ echo $z 5+1 $ z=`expr $z + 1` $ echo $z 6
3. let
let也是对空格敏感的, 不过与expr相反, 其+号附近不能有空格(略难记啊...:(), let语句中还可以省略$符号
$ let z=5 $ echo $z 5 $ let z=$z+1 $ echo $z 6 $ let z=$z + 1 # --- Spaces around + sign are bad with let -bash: let: +: syntax error: operand expected (error token is "+") $let z=z+1 # --- look Mom, no $ to read a variable. $echo $z 7
let的另一种形式是用双括号把数学计算的语句包围起来, 而且对空格比较宽容, 在+号附近有无空格都可以
$ ((e=5)) $ echo $e 5 $ (( e = e + 3 )) $ echo $e 8 $ (( e=e+4 )) # -- spaces or no spaces, it doesn't matter $ echo $e 12
4. bc
let不支持浮点数操作, 这时候需要用到bc
$let r=3.5 -bash: let: r=3.5: syntax error in expression (error token is ".5") $(( r = 3.5 )) -bash: ((: r = 3.5 : syntax error in expression (error token is ".5 ")
bc既可以以交互的方式执行, 也可以作为shell的一个命令.
交互方式:
$ bc bc 1.06 Copyright 1991-1994, 1997, 1998, 2000 Free Software Foundation, Inc. This is free software with ABSOLUTELY NO WARRANTY. For details type `warranty'. 3 + 2 5 obase=2 12 1100 <cntrl-d>
作为shell的一个命令:
$r=3.5 $s=`echo "$r + 2.2" | bc` $echo $s 5.7 $ z = `echo $z + 1 | bc` -bash: z: command not found # =号附近不能有空格, 这是shell的语法限制的, 不是bc $ z=`echo "$z + 1" | bc` $ echo $z 8 $ z=`echo "$z+1" | bc` #bc中对空格不敏感 $ echo $z 9
5. 其他
网上有人总结了一个非常全的各种shell中数学计算的方法[2]:
$ echo $((20.0/7)) $ zcalc $ bc <<< 20+5/2 $ bc <<< 'scale=4;20+5/2' $ expr 20 + 5 $ calc 2 + 4 $ node -pe 20+5/2 # Uses the power of JavaScript, e.g. : node -pe 20+5/Math.PI $ echo 20 5 2 / + p | dc $ echo 4 k 20 5 2 / + p | dc $ perl -E "say 20+5/2" $ python -c "print 20+5/2" $ python -c "print 20+5/2.0" $ clisp -x "(+ 2 2)" $ lua -e "print(20+5/2)" $ php -r 'echo 20+5/2;' $ ruby -e 'p 20+5/2' $ ruby -e 'p 20+5/2.0' $ guile -c '(display (+ 20 (/ 5 2)))' $ guile -c '(display (+ 20 (/ 5 2.0)))' $ slsh -e 'printf("%f",20+5/2)' $ slsh -e 'printf("%f",20+5/2.0)' $ tclsh <<< 'puts [expr 20+5/2]' $ tclsh <<< 'puts [expr 20+5/2.0]' $ sqlite3 <<< 'select 20+5/2;' $ sqlite3 <<< 'select 20+5/2.0;' $ echo 'select 1 + 1;' | sqlite3 $ psql -tAc 'select 1+1 $ R -q -e 'print(sd(rnorm(1000)))' $ r -e 'cat(pi^2, "\n")' $ r -e 'print(sum(1:100))' $ smjs $ jspl
参考文献:
[2]. How to do integer & float calculations, in bash or other languages/frameworks?
[3]. Shell中数学计算总结