数值和运算
Bash 支持整数和浮点数,并且支持基本的数学运算。内置的命令 expr
,let
,(())
只支持整数运算。至于浮点数运算可以使用 bc
。本文后续将bc介绍浮点数运算。 随着Bash版本的演进,现在推荐使用(())
进行算术运算。这里主要介绍(())
,let
和expr
也会简单描述一下
表达式
- 使用
((...))
语法结构进行整数运算,((...))
支持C语言
风格的算术表达式。((...))
内会忽略空格,字符串会被当做变量引用变量处理,$
可以省略 ((...))
可以理解为命令,其并不返回计算结果,((...))
命令执行结果由算术表达式的计算结果决定,计算结果不为0时,((...))
命令执行成功,为0时,((...))
命令执行失败。- 若要获取计算结果可以使用
$((...))
,$((...))
不是命令,不能单独执行,只能被其他命令引用。
#!/bin/bash
((sum=1+2+3+4+5))
echo $? # 输出0,命令执行成功
echo $sum # 输出10
# 直接执行
echo $((1+2+3+4+5))
males=20
females=30
total=$((males+females)) # 变量males和females的值被使用,并且省略了$
echo $total
echo $((total = males + females + 1)) # 输出51
# (()) 在处理字符串会递归下去,直到找到相应的变量,或者变量不存在
males=temp
temp=11
echo $((total = males + females + 1)) # 输出42
echo $((1.0 + 2)) # 语法错误
echo $(("jartap" + 2)) # 在Bash不同版本中执行情况可能不同,4.2版本执行错误,4.4版本输出2
在((...))
中可以使用()
调整优先级,((...))
支持的运算符有:
- +:加法
- -:减法
- *:乘法
- /:除法,整除:抹除小数部分,例如余数是5.5,则结果为5
- %:余数
- **:指数
- ++:自增运算,可以为前缀或后缀
- –:自减运算,可以为前缀或后缀
优先级:
- 括号:首先计算括号内的表达式。
- 自增、自减:自增和自减的优先级高于指数运算。
- 指数(**):优先级高于加减乘除,但是优先级低于括号。
- 乘法和除法(*, /,%):从左到右计算乘法和除法,它们具有相同的优先级。
- 加法和减法(+, -):然后从左到右计算加法和减法,它们也具有相同的优先级。
数值常量
在变量章节中,我们知道Bash变量是没有类型的,其都是字符串;但是Bash会根据字符串的内容,自动识别其类型,比如数字字符串会被识别为数字类型,而字母字符串会被识别为字符串类型。Bash中,数字类型有四种:1. 十进制数字;2. 十六进制数字;3. 八进制数字。 默认情况下数字类型是十进制数字,其基本形式如下:
- num,默认十进制数
- 0xnum,十六进制数
- 0num,八进制数
- base#num,base进制的数据,num中的数字不能超过base进制的表示范围,例如可以用2#1010表示二进制数(1010),其十进制表示为10
我们来看些示例:
echo $((0x41)) # 输出:65,等价于$((16#41))
echo $((2#1000001)) # 输出:65
a=10
b=0xA
echo "$a" # 10
echo "$b" # 0xA
echo $((a+b)) # 20
位运算
(())
还支持位运算符,位运算符一般低于算术运算符:
<<
:位左移运算,把一个数字的所有位向左移动指定的位。>>
:位右移运算,把一个数字的所有位向右移动指定的位。&
:位的“与”运算,对两个数字的所有位执行一个AND操作。|
:位的“或”运算,对两个数字的所有位执行一个OR操作。~
:位的“否”运算,对一个数字的所有位取反。^
:位的异或运算(exclusive or),对两个数字的所有位执行一个异或操作。
看一些示例:
#!/bin/bash
# ------------------------<<位左移运算-------------------------------------
a=5 # 二进制表示为 0101
((b = a << 2)) # 左移2位
echo $b # 输出:20,二进制表示为 10100
# ------------------------>>位右移运算-------------------------------------
c=20 # 二进制表示为 10100
((d = c >> 2)) # 右移2位
echo $d # 输出:5,二进制表示为 0101
# ------------------------&位与运算----------------------------------------
# 对 6(二进制 110)和 3(二进制 011)执行位与操作
result=$((6 & 3))
echo "6 & 3 = $result" # 输出: 6 & 3 = 2
# ------------------------&位或运算----------------------------------------
# 对 6(二进制 110)和 3(二进制 011)执行位或操作
result=$((6 | 3))
echo "6 | 3 = $result" # 输出: 6 | 3 = 7
# ------------------------&位否运算----------------------------------------
# 对 5(二进制 0101)执行位否操作,注意 Bash 使用 32 位整数
# 因此,结果将是 -6,因为在补码表示中,对 0101 取反得到 1010...(前面还有很多 1)
# 然后加 1 变成补码形式的 -6
result=$((~5))
echo "~5 = $result" # 输出可能是: ~5 = -6,具体取决于系统如何处理整数
# ------------------------&位或运算----------------------------------------
# 对 6(二进制 110)和 3(二进制 011)执行位异或操作
result=$((6 ^ 3))
echo "6 ^ 3 = $result" # 输出: 6 ^ 3 = 5
赋值运算
(())
可以进行赋值运算,如:
((a=1+1))
echo $a # 输出:2
# 当使用
echo $((a=1+1)) # 输出:2,$(())会返回最后一个表达式的值作为返回值,多个表达式之间用逗号分隔
echo $((a=1+2, b=2+2)) # 输出:4, 甚至可以直接分隔数字
echo $a,$b # 输出:3,4
echo $((1, 2)) # 输出:2
逻辑运算
(())
支持逻辑运算符:
<
:小于>
:大于<=
:小于或相等>=
:大于或相等==
:相等!=
:不相等&&
:逻辑与||
:逻辑或!
:逻辑否expr1?expr2:expr3
:三元条件运算符。若表达式expr1的计算结果为非零值(算术真),则执行表达式expr2,否则执行表达式expr3。
let 命令
与let
命令类似,(( ... ))
结构允许对算术表达式的扩展和求值。它是let命令的简化形式。例如,a=$(( 5 + 3 ))
会将变量a赋值成 5 + 3,也就是8。在Bash中,双圆括号结构也允许以C风格的方式操作变量。例如,(( var++ ))
。
expr 命令
expr
: evalute(求值)expressions(表达式))命令既可以用于整数运算,也可以用于相关字符串长度、匹配等运算处理