本博客已經遷往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中數學計算總結