1.算术表达式
((...))
语法可以进行整数的算术运算,比如下面这样:
((foo = 5 + 5))
echo $foo
结果为:
((...))
会自动忽略内部的空格,所以下面的写法都正确,得到同样的结果。
((2+2))
(( 2+2 ))
(( 2 + 2 ))
这个语法不返回值,命令执行的结果根据算术运算的结果而定。只要算术结果不是0
,命令就算执行成功。
(( 3 + 2 ))
echo $?
上面例子中,3 + 2
的结果是5,命令就算执行成功,环境变量$?
为0
:
如果算术结果为0
,命令就算执行失败。
(( 3 - 3 ))
echo $?
上面例子中,3 - 3
的结果是0
,环境变量$?
为1
,表示命令执行失败。
如果要读取算术运算的结果,需要在((...))
前面加上美元符号$((...))
,使其变成算术表达式,返回算术运算的值。
echo $((2 + 2))
((...))
语法支持的算术运算符如下。
+
:加法-
:减法*
:乘法/
:除法(整除)%
:余数**
:指数++
:自增运算(前缀或后缀)--
:自减运算(前缀或后缀)
注意,除法运算符的返回结果总是整数,比如5
除以2
,得到的结果是2
,而不是2.5
:
++
和--
这两个运算符有前缀和后缀的区别。作为前缀是先运算后返回值,作为后缀是先返回值后运算,这和C/C++语言中的自增自减效果一致。
i=0
echo $i
echo $((i++))
echo $i
echo $((++i))
echo $i
上面例子中,++
作为后缀是先返回值,执行echo
命令,再进行自增运算;作为前缀则是先进行自增运算,再返回值执行echo
命令:
$((...))
内部可以用圆括号改变运算顺序。
echo $(( (2 + 3) * 4 ))
上面例子中,内部的圆括号让加法先于乘法执行。
$((...))
结构可以嵌套。
echo $(((5**2) * 3))
# 等同于
echo $(($((5**2)) * 3))
这个语法只能计算整数,使用小数会报错:
$((...))
的圆括号之中,不需要在变量名之前加上$
,不过加上也不报错。
number=2
echo $(($number + 1))
上面例子中,变量number
前面有没有美元符号,结果都是一样的。
如果在$((...))
里面使用字符串,Bash 会认为那是一个变量名。如果不存在同名变量,Bash 就会将其作为空值,因此不会报错。
echo $(( "hello" + 2))
echo $(( "hello" * 2))
上面例子中,"hello"
会被当作变量名,返回空值,而$((...))
会将空值当作0
,所以乘法的运算结果就是0
。同理,如果$((...))
里面使用不存在的变量,也会当作0
处理:
如果一个变量的值为字符串,跟上面的处理逻辑是一样的。即该字符串如果不对应已存在的变量,在$((...))
里面会被当作空值。
foo=hello
echo $(( foo + 2))
上面例子中,变量foo
的值是hello
,而hello
也会被看作变量名。这使得有可能写出动态替换的代码。