Shell 运算符

Shell 支持多种运算符,这里我们以 Bash 为例,介绍算术运算符、关系运算符、布尔运算符、字符串运算符和文件测试运算符的用法。

算术运算符

运算符 说明 举例
+ 加法 $(($a + $b))$((a + b))`expr $a + $b`
减法 $(($a - $b))$((a - b))`expr $a - $b`
* 乘法 $(($a * $b))$((a * b))`expr $a * $b`
/ 除法 $(($a / $b))$((a / b))`expr $a / $b`
% 取余 $(($a % $b))$((a % b))`expr $a % $b`
= 赋值 a=$b 将把变量 b 的值赋给 a。

说明:双小括号表示其中进行数字类型的计算(而且只支持整型),双小括号中还支持布尔值判定,并且当被双小括号框中,整体就应该被看成一个变量。另外,双小括号中支持 C 语言语法规则,可以不加美元符,可以再加单小括号把一些运算先括起来等。

# 默认 a 是字符串类型
a=1;
# 把 a 看成数字,改变前面定义的变量时,必须要加双小括号,或者用 let 语句,否则会把其视为字符串类型
((a++));
let "a++";
# 输出,双小括号应该被看成一个变量
echo $((a+1));

expr 是一款表达式计算工具,使用它能在 shell 中完成表达式的求值操作。但需要注意,expr 表达式要使用反引号包裹,并且表达式和运算符之间要有空格。

关系运算符

关系运算符只支持数字,不支持字符串,除非字符串的值是数字。

运算符 说明 举例
-eq 检测两个数是否相等,相等返回 true。 [ $a -eq $b ]
-ne 检测两个数是否相等,不相等返回 true。 [ $a -ne $b ]
-gt 检测左边的数是否大于右边的,如果是,则返回 true。 [ $a -gt $b ]
-lt 检测左边的数是否小于右边的,如果是,则返回 true。 [ $a -lt $b ]
-ge 检测左边的数是否大于等于右边的,如果是,则返回 true。 [ $a -ge $b ]
-le 检测左边的数是否小于等于右边的,如果是,则返回 true。 [ $a -le $b ]
== 用于比较两个数字,相同则返回 true。 [ a == b ]
!= 用于比较两个数字,不相同则返回 true。 [ a != b ]

注意:条件表达式要放在方括号之间,并且要有空格

布尔运算符

运算符 说明 举例
! 非运算,表达式为 true 则返回 false,否则返回 true。 [ !false ]
-o 或运算,有一个表达式为 true 则返回 true。 [ $a -lt 20 -o $b -gt 100 ]
|| 或运算,与 -o 相似。 [ $a -lt 20 ] || [ $b -gt 100 ]
-a 与运算,两个表达式都为 true 才返回 true。 [ $a -lt 20 -a $b -gt 100 ]
&& 与运算,与 -a 相似。 [ $a -lt 20 ] && [ $b -gt 100 ]

字符串运算符

运算符 说明 举例
-z 如果字符串长度为零,则返回 true [ -z $myStr ]
-n 如果字符串长度非零,则返回 true [ -n $myStr ]
== 如果两个字符串相同,则返回 true [ $myStr = "getiot" ]
!= 如果两个字符串不同,则返回 true [ $myStr != "getiot" ]

文件测试运算符

文件测试运算符用于检测 Linux 文件的各种属性,在对文件进行操作之前先检查文件属性,是个好的编程习惯。

运算符 说明 举例
-b 检测文件是否是块设备文件,如果是,则返回 true。 [ -b $file ]
-c 检测文件是否是字符设备文件,如果是,则返回 true。 [ -c $file ]
-d 检测文件是否是目录,如果是,则返回 true。 [ -d $file ]
-f 检测文件是否是普通文件(既不是目录,也不是设备文件),如果是,则返回 true。 [ -f $file ]
-p 检测文件是否是有名管道,如果是,则返回 true。 [ -p $file ]
-r 检测文件是否可读,如果是,则返回 true。 [ -r $file ]
-w 检测文件是否可写,如果是,则返回 true。 [ -w $file ]
-x 检测文件是否可执行,如果是,则返回 true。 [ -x $file ]
-s 检测文件是否为空(文件大小是否大于0),不为空返回 true。 [ -s $file ]
-e 检测文件(包括目录)是否存在,如果是,则返回 true。 [ -e $file ]
-S 检测文件是否为 socket,如果是,则返回 true。 [ -S $file ]
-L 检测文件是否存在并且是一个符号链接,如果是,则返回 true。 [ -L $file ]

特别注意

== 和 = 的区别

有时候,原来运行得好好的 shell 程序,换个平台就运行不了,例如下面 shell 程序。

#!/bin/sh

if [ $1 == "hello" ]; then
    echo "Well done!"
fi

在 Ubuntu 上运行,会出现如下的错误:

[: ==: unexpected operator

这是因为 shell 脚本开头使用 #!/bin/sh,而不是 #!/bin/bash。而 /bin/sh 使用的是 dash,dash 中默认的判断语句是 =,而不是 bash 使用的 ==

$ ls -l /bin/sh
lrwxrwxrwx 1 root root 4 5月  28 20:16 /bin/sh -> dash

解决方法是直接使用 = 符号进行判断,但这样做可能会导致该脚本在其他平台无法正常运行(例如不支持 dash 的嵌入式平台)。为了更好地兼容,可以在 shell 脚本开头使用 #!/bin/bash,或者使用下面命令将系统默认的 shell 链接由 dash 改为 bash。

sudo dpkg-reconfigure dash

选择“否”即可。

Leave a Reply