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

参考文献:

[1]. Math in Shell Scripts

[2]. How to do integer & float calculations, in bash or other languages/frameworks?

[3]. Shell中数学计算总结

posted on 2014-01-27 20:45 潘的博客 阅读(...) 评论(...) 编辑 收藏

导航

统计