bash的算术运算
bash共支持三种算术运算方式
- let 表达式
- expr 表达式
- 双括号表达式
- let表达式:let var=
let表达式的第一个参数通常时一个变量,把运算表达式的结果存入变量。
#!/bin/bash
x=3
y=5
let z1=3+5; echo $z1 # output: 8, notice no whitespace is allowed.
# let z = 3 + 5 # invalid
let "z2=3+5"; echo $z2 # output: 8
let "z3 = 3 + 5 "; echo $z3 # output: 8
let z1=x+y; echo $z1 # output: 8
# let z = x + y # invalid
let "z2=x+y"; echo $z2 # output: 8
let "z3 = x + y "; echo $z3 # output: 8
let z1=$x+$y; echo $z1 # output: 8
# let z = $z + $y # invalid
let "z2=$x+$y"; echo $z2 # output: 8
let "z3 = $x + $y"; echo $z3 # output: 8
注意到,如果表达式没有用引号括起来,那么表达式中间不能有空格,这是因为,如果没有引号,那么表达式是由shell先来解析,shell无法识别含义,而如果带引号,那么shell只负责解析整个引号串作为字符串传递给let解析就可以了。
还支持自增模式:
#!/bin/bash
x=3
y=5
let x+=3; echo $x # output: 6
let "x++"; echo $x # output: 7
let "x += y"; echo $x # output: 12
let "x+=$y"; echo $x # output: 17
- expr表达式:expr
expr和let的差异是,expr并不把结果写到变量中,而是直接输出到屏幕;所以expr通常使用在表达式中,而不是一个独立的语句。
#!/bin/bash
x=3
y=5
expr 3+5 #output: 3+5
expr 3 + 5 #output: 8
expr "3+5" #output: 3+5
expr "3 + 5" #output: 3 + 5
expr "x+y" #output: x+y
expr "x + y" #output: x + y
expr $x+$y #output: 3+5
expr $x + $y #output: 8
expr "$x+$y" #output: 3+5
expr "$x + $y" #output: 3 + 5
哈哈,对照let语句,这么多写法,只有两条满足我们的需求,可见expr的使用就有限制的多了:
- 不能使用引号把表达式括起来。
- 算术运算符之间必须用空格分开。
不过如果好把expr的结果写到变量中 ,可以使用$()格式。
#!/bin/bash
x=3
y=5
z=$(expr $x + $y); echo $z #output: 8
- 双括号运算: $(( expression ))
双括号运行既可以赋值给变量,也可以输出到屏幕:
#!/bin/bash
x=3
y=5
((z=3+5)); echo $z # output: 8
((z = 3 + 5)); echo $z # output: 8
(( z = 3 + 5 )); echo $z # output: 8
((z=x+y)); echo $z # output: 8
((z = x + y)); echo $z # output: 8
(( z = x + y )); echo $z # output: 8
((z=$x+$y)); echo $z # output: 8
((z = $x + $x)); echo $z # output: 8
(( z = $x + $y )); echo $z # output: 8
或者
#!/bin/bash
x=3
y=5
z=$((3+5)); echo $z # output: 8
z=$((3 + 5)); echo $z # output: 8
z=$(( 3 + 5 )); echo $z # output: 8
z=$((x+y)); echo $z # output: 8
z=$((x + y)); echo $z # output: 8
z=$(( x + y )); echo $z # output: 8
z=$(($x+$y)); echo $z # output: 8
z=$(($x + $y)); echo $z # output: 8
z=$(( $x + $y )); echo $z # output: 8
可支持自增型运算:
#!/bin/bash
x=3
y=5
(( x++ )); echo $x # output: 4,注意这里没有$
(( y += 1 )); echo $y # output: 6
作为表达式使用:
#!/bin/bash
x=3
y=5
echo "z1="$((x+y)) # output: 8
echo "z2="$((x++)) # output: 3
echo "z3="$((++y)) # output: 6
echo "x=$x,y=$y" # x=4,y=6
echo "z4="$(($x+$y)) # output: 10
#echo "z5="$(($x++)) # invalid express
echo "z6="$((++$y)) # output: 6
echo "x=$x,y=$y" # x=4,y=6
这个地方需要注意:
- z2输出的是3,因为x++是后增型的,先输出x=3,然后计算x=x+1=4
- z3输出的是6,因为++y是先增型的,先计算y=y+1=6,然后输出z3=6
- z5是无效的,为什么?
- z6输出是4,为什么?
- 最后输出x=4,y=6,为什么y也等于6,前面不是++了吗?
注意z4,z5,z6的表达式中并没有使用双括号'(())'变量,而是使用了shell变量,这个变量表达式在传给双括号'(())'之前,已经被shell替换成了常量4或者6,这相当于在常量上做自增计算,结果自然是无效的。
因为其实际执行的是:
echo "z4="$((4+6)) # output: 10
#echo "z5="$((4++)) # invalid express
echo "z6="$((++6)) # output: 6
echo "x=$x,y=$y" # x=4,y=6
相当于在常量上做自增操作。
但是还是有疑问的是,为什么常量上可以做先自增操作,而不能做后自增操作。