运算符

Shell 的运算符种类不少,算术运算、比较运算、逻辑运算、文件测试各有各的语法。搞清楚这些,条件判断才能写对。

算术运算符

A=10
B=3

echo $((A + B))    # 加法:13
echo $((A - B))    # 减法:7
echo $((A * B))    # 乘法:30
echo $((A / B))    # 除法:3(取整)
echo $((A % B))    # 取余:1
echo $((A ** 2))   # 幂运算:100

自增自减:

N=5
((N++))    # N=6
((N--))    # N=5
((N+=3))   # N=8
((N-=2))   # N=6

复合赋值:

N=10
((N+=5))   # 等同于 N=N+5
((N*=2))   # 等同于 N=N*2

比较运算符

Shell 的比较运算符分两类:数字比较和字符串比较。这两套操作符不一样,容易混淆。

数字比较

用在 (( ))[ ] 中:

A=10
B=20

# 在 (( )) 中用数学符号
if ((A < B)); then
    echo "A 小于 B"
fi

# 在 [ ] 中用字母操作符
if [ $A -lt $B ]; then
    echo "A 小于 B"
fi

数字比较操作符:

操作符含义示例
-eq等于[ $A -eq $B ]
-ne不等于[ $A -ne $B ]
-gt大于[ $A -gt $B ]
-ge大于等于[ $A -ge $B ]
-lt小于[ $A -lt $B ]
-le小于等于[ $A -le $B ]

字符串比较

STR1="hello"
STR2="world"

if [ $STR1 = $STR2 ]; then
    echo "相等"
fi

if [ $STR1 != $STR2 ]; then
    echo "不相等"
fi

字符串比较操作符:

操作符含义
=相等
!=不相等
-z长度为零
-n长度非零
# 判断字符串为空
if [ -z "$STR" ]; then
    echo "字符串为空"
fi

# 判断字符串非空
if [ -n "$STR" ]; then
    echo "字符串非空"
fi

逻辑运算符

在 [ ] 中

# 与
if [ $A -gt 0 -a $A -lt 10 ]; then
    echo "A 在 0 到 10 之间"
fi

# 或
if [ $A -lt 0 -o $A -gt 10 ]; then
    echo "A 不在 0 到 10 之间"
fi

# 非
if [ ! -f "$FILE" ]; then
    echo "文件不存在"
fi

在 [[ ]] 中(推荐)

# 与
if [[ $A -gt 0 && $A -lt 10 ]]; then
    echo "A 在 0 到 10 之间"
fi

# 或
if [[ $A -lt 0 || $A -gt 10 ]]; then
    echo "A 不在 0 到 10 之间"
fi

# 非
if [[ ! -f $FILE ]]; then
    echo "文件不存在"
fi

[[ ]][ ] 更强大,支持正则匹配,不需要转义:

# 正则匹配
if [[ $STR =~ ^[0-9]+$ ]]; then
    echo "是数字"
fi

文件测试运算符

判断文件属性:

FILE="/etc/passwd"

if [ -e $FILE ]; then
    echo "文件存在"
fi

if [ -f $FILE ]; then
    echo "是普通文件"
fi

if [ -d $FILE ]; then
    echo "是目录"
fi

常用文件测试操作符:

操作符含义
-e存在
-f普通文件
-d目录
-r可读
-w可写
-x可执行
-s非空(大小大于0)
-L符号链接

文件比较:

FILE1="a.txt"
FILE2="b.txt"

if [ $FILE1 -nt $FILE2 ]; then
    echo "FILE1 比 FILE2 新"
fi

if [ $FILE1 -ot $FILE2 ]; then
    echo "FILE1 比 FILE2 旧"
fi

位运算符

A=5    # 二进制:101
B=3    # 二进制:011

echo $((A & B))    # 与:001 = 1
echo $((A | B))    # 或:111 = 7
echo $((A ^ B))    # 异或:110 = 6
echo $((~A))       # 取反
echo $((A << 2))   # 左移:10100 = 20
echo $((A >> 1))   # 右移:10 = 2

三元运算符

Shell 没有真正的三元运算符,但可以用 &&|| 模拟:

A=10
B=20

# 类似 A > B ? "大" : "小"
[[ $A -gt $B ]] && echo "大" || echo "小"

注意这个技巧在 echo 前面的命令失败时可能出问题,复杂情况还是用 if。

小结

运算符使用要点:

  1. 数字比较用 -eq-lt 等,或用 (( ))
  2. 字符串比较用 =!=
  3. 推荐用 [[ ]] 代替 [ ]
  4. 文件测试用 -f-d-e
  5. 算术运算用 $(( ))