Bash Shell 本身一些内置命令可以执行简单的整数运算,但复杂一些的运算(比如浮点数运算)需要通过一些外部命令来实现,Bash Shell 数学运算符只支持整数运算。
(( ))
、let
、$[ ]
(方括号并不是所有的 Shell 都支持)expr
、bc
、awk
从运行效率来看,Bash Shell 内置命令的执行效率要高于外部命令,(( ))
执行效率最高,其次是 let
,外部命令执行效率相对来说较低。
【注】expr
运算在运算符和变量之间需要用空格分开,如果进行乘法运算,还需要对乘号进行转义 \*
,否则 Bash Shell 会把乘号解释为通配符而报错。Bash Shell 内置命令和 expr
都不能进行浮点运算,但 bc
和 awk
可以。
整数运算 | 示例 |
---|---|
加 | ((i=i+1))、((i++))、((++i))、((i+=1)) let i=i+1、let i++、let ++i、let i+=1 i=$[i+1]、i=$[i++]、i=$[++i]、i=$[i+=1] (++i 和 i++ 的区别同 C 语言) i=$(expr $i + 1) i=$(echo $i+1 | bc) i=$(ehco "$i 1" | awk '{printf $1+$2;}') |
减 | ((i=i-1))、((i--))、((--i))、((i-=1)) let i=i-1、let i--、 let --i、let i-=1 i=$[i-1]、i=$[i--]、i=$[--i]、i=$[i-=1] (--i 和 i-- 的区别同 C 语言) i=$(expr $i - 1) i=$(echo $i-1 | bc) i=$(ehco "$i 1" | awk '{printf $1-$2;}') |
乘 | ((i=i*2))、((i*=2)) let i=i*2、let i*=2 i=$(expr $i \* 2)(乘号需要转义) i=$[i*2]、i=$[i*=2] i=$(echo $i*2 | bc) i=$(ehco "$i 2" | awk '{printf $1*$2;}') |
除 | ((i=i/2))、((i/=2)) let i=i/2、let i/=2 i=$[i/2]、i=$[i/=2] i=$(expr $i / 2) i=$(echo $i/2 | bc) i=$(ehco "$i 2" | awk '{printf $1/$2;}') |
取模 | ((i=i%2))、((i%=2)) let i=i%2、let i%=2 i=$[i%2]、i=$[i%=2] i=$(expr $i % 2) i=$(echo $i%2 | bc) i=$(echo "$i 2" | awk '{printf $1%$2;}') |
求幂 | ((i=i**2)) let i=i**2 i=$[i**2] i=$(echo $i^2 | bc) i=$(echo "$i 2" | awk '{printf $1**$2;}') i=$(echo "$i 2" | awk '{printf $1^$2;}') (awk 求幂既支持 ** 运算符也支持 ^ 运算符) |
移位 | ((i=i<<1))、((i<<=1))、((i=i>>1))、((i>>=1)) let i=i<<1、let i<<=1、let i=i>>1、let i>>=1 i=$[i<<1]、i=$[i<<=1]、i=$[i>>1]、i=$[i>>=1] (expr、bc 均不支持移位运算) i=$(echo "$i 1" | awk '{printf lshift($1,$2);}') i=$(echo "$i 1" | awk '{printf rshift($1,$2);}') |
位取反 | ((i=~i)) let i=~i i=$[~i] (expr、bc 均不支持位取反运算) i=$(echo "$i" | awk -M '{printf compl($i);}') 【注】-M 参数指定 awk 以任意精度计算(默认为 53 位,不加 -M 会有较大误差且无法对 64 位整数取反) |
位与 | ((i=i&2))、((i&=2)) let i=i&2、let i&=2 i=$[i&2]、i=$[i&=2] (expr、bc 均不支持位与运算) i=$(echo "$i 2" | awk '{printf and($1,$2);}') |
位或 | ((i=i|2))、((i|=2)) let i=i|2、let i|=2 i=$[i|2]、i=$[i|=2] (expr、bc 均不支持位或运算) i=$(echo "$i 2" | awk '{printf or($1,$2);}') |
位异或 | ((i=i^2))、((i^=2)) let i=i^2、let i^=2 i=$[i^2]、i=$[i^=2] (expr、bc 均不支持位或运算) i=$(echo "$i 2" | awk '{printf xor($1,$2);}') |
【注】bc
在进行浮点运算时需要用 scale
指定小数位数,否则默认为 0,即结果只保留整数;或者不使用 scale
指定小数位数而使用 bc -l
,默认小数精度为 20 位。awk
通过 printf
的格式控制来控制小数位数。
外部命令 | 示例 |
---|---|
bc | echo "scale = 5; 0.5+0.5" | bc echo "scale = 5; 0.5-0.5" | bc echo "scale = 5; 0.5*0.5" | bc echo "scale=5; 1/3" | bc echo "scale = 5; 0.5^2" | bc 【注】bc 不支持求小数幂,只支持求整数幂,即 ^ 运算符右边参数必须为整数。 |
awk | echo "0.5 0.5" | awk '{printf("%0.5f\n",$1+$2);}' echo "0.5 0.5" | awk '{printf("%0.5f\n",$1-$2);}' echo "0.5 0.5" | awk '{printf("%0.5f\n",$1*$2);}' echo "1 3" | awk '{printf("%0.5f\n",$1/$2);}' echo "0.5 0.5" | awk '{printf("%0.5f\n",$1**$2);}' echo "0.5 0.5" | awk '{printf("%0.5f\n",$1^$2);}' |
bc
命令提供了数学函数库(需指定 -l
选项,该选项默认小数精度为 20 位),包含了一些基本的数学函数(以下三角函数均采用弧度值):
函数 | 命令 | 示例 |
---|---|---|
sin(x) | s(x) | echo "s($x)" | bc -l |
cos(x) | c(x) | echo "c($x)" | bc -l |
arctan(x) | a(x) | echo "a($x)" | bc -l |
ln(x) | l(x) | echo "l($x)" | bc -l |
exp(x) | e(x) | echo "e($x)" | bc -l |
开方 | sqrt(x) | echo "sqrt($x)" | bc -l |
… | … | … |
awk
命令同样提供了一些基本数学函数:
函数 | 命令 | 示例 |
---|---|---|
sin(x) | sin(x) | echo "$i" | awk '{printf sin($1);}' |
cos(x) | cos(x) | echo "$i" | awk '{printf cos($1);}' |
arctan(x) | atan2(y,x) | echo "$i $j" | awk '{printf atan2($1,$2);}' |
ln(x) | log(x) | echo "$i" | awk '{printf log($1);}' |
exp(x) | exp(x) | echo "$i" | awk '{printf exp($1);}' |
开方 | sqrt(x) | echo "$i" | awk '{printf sqrt($1);}' |
… | … | … |