Shell 基本运算符
Shell 和其他编程语言一样,支持多种运算符,包括:算数运算符关系运算符布尔运算符字符串运算符文件测试运算符原生bash不支持简单的数学运算,但是可以通过其他命令来实现,例如 awk 和 expr,expr 最常用。expr 是一款表达式计算工具,使用它能完成表达式的求值操作。例如,两个数相加(注意使用的是反引号 ` 而不是单引号 '):实例#!/bin/bashval=`expr 2 + 2`echo "两数之和为 : $val"运行实例 »执行脚本,输出结果如下所示:两数之和为 : 4两点注意:表达式和运算符之间要有空格,例如 2+2 是不对的,必须写成 2 + 2,这与我们熟悉的大多数编程语言不一样。完整的表达式要被 ` ` 包含,注意这个字符不是常用的单引号,在 Esc 键下边。算术运算符下表列出了常用的算术运算符,假定变量 a 为 10,变量 b 为 20:运算符说明举例+加法`expr $a + $b` 结果为 30。-减法`expr $a - $b` 结果为 -10。*乘法`expr $a \* $b` 结果为 200。/除法`expr $b / $a` 结果为 2。%取余`expr $b % $a` 结果为 0。=赋值a=$b 将把变量 b 的值赋给 a。==相等。用于比较两个数字,相同则返回 true。[ $a == $b ] 返回 false。!=不相等。用于比较两个数字,不相同则返回 true。[ $a != $b ] 返回 true。注意:条件表达式要放在方括号之间,并且要有空格,例如: [$a==$b] 是错误的,必须写成 [ $a == $b ]。实例算术运算符实例如下:实例#!/bin/bash# author:菜鸟教程# url:www.runoob.coma=10b=20val=`expr $a + $b`echo "a + b : $val"val=`expr $a - $b`echo "a - b : $val"val=`expr $a \* $b`echo "a * b : $val"val=`expr $b / $a`echo "b / a : $val"val=`expr $b % $a`echo "b % a : $val"if [ $a == $b ]thenecho "a 等于 b"fiif [ $a != $b ]thenecho "a 不等于 b"fi执行脚本,输出结果如下所示:a + b : 30a - b : -10a * b : 200b / a : 2b % a : 0a 不等于 b注意:乘号(*)前边必须加反斜杠(\)才能实现乘法运算;if...then...fi 是条件语句,后续将会讲解。在 MAC 中 shell 的 expr 语法是:$((表达式)),此处表达式中的 "*" 不需要转义符号 "\" 。------------------------------------------------------------------------------------------Shell 相加目前发现有 3 种写法:1.a=10b=20c=`expr ${a} + ${b}`echo "$c"2.c=$[ `expr 10 + 20` ]echo "$c"3.c=$[ 10 + 20 ]echo "$c"初学者推荐第一种写法,虽然看着复杂,但逻辑清晰,不易混淆。推荐用 $() 代替 ``:val=`expr 10 + 20`val=$(expr 10 + 20)相加补充一种方式:a=10b=20c=$(($a+$b))关系运算符关系运算符只支持数字,不支持字符串,除非字符串的值是数字。下表列出了常用的关系运算符,假定变量 a 为 10,变量 b 为 20:运算符说明举例-eq检测两个数是否相等,相等返回 true。[ $a -eq $b ] 返回 false。-ne检测两个数是否不相等,不相等返回 true。[ $a -ne $b ] 返回 true。-gt检测左边的数是否大于右边的,如果是,则返回 true。[ $a -gt $b ] 返回 false。-lt检测左边的数是否小于右边的,如果是,则返回 true。[ $a -lt $b ] 返回 true。-ge检测左边的数是否大于等于右边的,如果是,则返回 true。[ $a -ge $b ] 返回 false。-le检测左边的数是否小于等于右边的,如果是,则返回 true。[ $a -le $b ] 返回 true。单词解释:EQ : EQUAL,['ikwəl],“=“NE : NOT EQUAL,“!=“GT : GREATER THAN,[ɡreɪt],“>“LT : LESS THAN,[les],“<“GE : GREATER THAN OR EQUAL,,">="LE : LESS THAN OR EQUAL ,,"<="实例关系运算符实例如下:实例#!/bin/bash# author:菜鸟教程# url:www.runoob.coma=10b=20if [ $a -eq $b ]thenecho "$a -eq $b : a 等于 b"elseecho "$a -eq $b: a 不等于 b"fiif [ $a -ne $b ]thenecho "$a -ne $b: a 不等于 b"elseecho "$a -ne $b : a 等于 b"fiif [ $a -gt $b ]thenecho "$a -gt $b: a 大于 b"elseecho "$a -gt $b: a 不大于 b"fiif [ $a -lt $b ]thenecho "$a -lt $b: a 小于 b"elseecho "$a -lt $b: a 不小于 b"fiif [ $a -ge $b ]thenecho "$a -ge $b: a 大于或等于 b"elseecho "$a -ge $b: a 小于 b"fiif [ $a -le $b ]thenecho "$a -le $b: a 小于或等于 b"elseecho "$a -le $b: a 大于 b"fi执行脚本,输出结果如下所示:10 -eq 20: a 不等于 b10 -ne 20: a 不等于 b10 -gt 20: a 不大于 b10 -lt 20: a 小于 b10 -ge 20: a 小于 b10 -le 20: a 小于或等于 b----------------------------------------------------------------------使用 [[ ... ]] 条件判断结构,而不是 [ ... ],能够防止脚本中的许多逻辑错误。比如,&&、||、< 和 > 操作符能够正常存在于 [[ ]] 条件判断结构中,但是如果出现在 [ ] 结构中的话,会报错。---------------------------------------------------------------------布尔运算符下表列出了常用的布尔运算符,假定变量 a 为 10,变量 b 为 20:运算符说明举例!非运算,表达式为 true 则返回 false,否则返回 true。[ ! false ] 返回 true。-o或运算,有一个表达式为 true 则返回 true。[ $a -lt 20 -o $b -gt 100 ] 返回 true。-a与运算,两个表达式都为 true 才返回 true。[ $a -lt 20 -a $b -gt 100 ] 返回 false。实例布尔运算符实例如下:实例#!/bin/bash# author:菜鸟教程# url:www.runoob.coma=10b=20if [ $a != $b ]thenecho "$a != $b : a 不等于 b"elseecho "$a == $b: a 等于 b"fiif [ $a -lt 100 -a $b -gt 15 ]thenecho "$a 小于 100 且 $b 大于 15 : 返回 true"elseecho "$a 小于 100 且 $b 大于 15 : 返回 false"fiif [ $a -lt 100 -o $b -gt 100 ]thenecho "$a 小于 100 或 $b 大于 100 : 返回 true"elseecho "$a 小于 100 或 $b 大于 100 : 返回 false"fiif [ $a -lt 5 -o $b -gt 100 ]thenecho "$a 小于 5 或 $b 大于 100 : 返回 true"elseecho "$a 小于 5 或 $b 大于 100 : 返回 false"fi执行脚本,输出结果如下所示:10 != 20 : a 不等于 b10 小于 100 且 20 大于 15 : 返回 true10 小于 100 或 20 大于 100 : 返回 true10 小于 5 或 20 大于 100 : 返回 false逻辑运算符以下介绍 Shell 的逻辑运算符,假定变量 a 为 10,变量 b 为 20:运算符说明举例&& AND [[ $a -lt 100 && $b -gt 100 ]] 返回 false|| OR [[ $a -lt 100 || $b -gt 100 ]] 返回 true实例逻辑运算符实例如下:实例#!/bin/bash# author:菜鸟教程# url:www.runoob.coma=10b=20if [[ $a -lt 100 && $b -gt 100 ]]thenecho "返回 true"elseecho "返回 false"fiif [[ $a -lt 100 || $b -gt 100 ]]thenecho "返回 true"elseecho "返回 false"fi执行脚本,输出结果如下所示:返回 false返回 true字符串运算符下表列出了常用的字符串运算符,假定变量 a 为 "abc",变量 b 为 "efg":运算符说明举例=检测两个字符串是否相等,相等返回 true。[ $a = $b ] 返回 false。!=检测两个字符串是否相等,不相等返回 true。[ $a != $b ] 返回 true。-z检测字符串长度是否为0,为0返回 true。[ -z $a ] 返回 false。-n检测字符串长度是否非 0,非 0 返回 true。[ -n "$a" ] 返回 true。$检测字符串是否非空,非空返回 true。[ $a ] 返回 true。实例字符串运算符实例如下:实例#!/bin/bash# author:菜鸟教程# url:www.runoob.coma="abc"b="efg"if [ $a = $b ]thenecho "$a = $b : a 等于 b"elseecho "$a = $b: a 不等于 b"fiif [ $a != $b ]thenecho "$a != $b : a 不等于 b"elseecho "$a != $b: a 等于 b"fiif [ -z $a ]thenecho "-z $a : 字符串长度为 0"elseecho "-z $a : 字符串长度不为 0"fiif [ -n "$a" ]thenecho "-n $a : 字符串长度不为 0"elseecho "-n $a : 字符串长度为 0"fiif [ $a ]thenecho "$a : 字符串不为空"elseecho "$a : 字符串为空"fi执行脚本,输出结果如下所示:abc = efg: a 不等于 babc != efg : a 不等于 b-z abc : 字符串长度不为 0-n abc : 字符串长度不为 0abc : 字符串不为空-----------------------------------------------------------------------------1、进行数值比较时,可以使用 [ expression1 OPexpression2 ],OP 可以为 -gt、-lt、-ge、-le、-eq、-ne 也可以使用 ((expression1 OP expression2)),OP 可以为 >、<、>=、<=、==、!=。这几个关系运算符都是测试整数表达式 expression1 和 expression2 之间的大小关系。2、 >、<、==、!= 也可以进行字符串比较。3、进行字符串比较时,== 可以使用 = 替代。4、 == 和 !=进行字符串比较时,可以使用 [ string1 OP string2 ] 或者 [[ string1 OP string2 ]] 的形式。5、 > 和 < 进行字符串比较时,需要使用[[ string1 OP string2 ]] 或者 [ string1 \OP string2 ]。也就是使用 [] 时,> 和 < 需要使用反斜线转义[] 表达式注意:在 [] 表达式中,常见的 >, < 需要加转义字符,表示字符串大小比较,以 acill 码位置作为比较。不直接支持 >, < 运算符,还有逻辑运算符 || 、&& ,它需要用 -a[and] –o[or] 表示。[[ ]] 表达式注意:[[]] 运算符只是 [] 运算符的扩充。能够支持 >, < 符号运算不需要转义符,它还是以字符串比较大小。里面支持逻辑运算符:|| && ,不再使用 -a -o。----------------------------------------------------------------------------字符串比较是否为 null 这里:#!/bin/basha=""if [ -n $a ]thenecho "-n $a : 字符串长度不为 0"elseecho "-n $a : 字符串长度为 0"fi输出结果为:-n : 字符串长度不为 0从结果上看 -n $a 返回 true 错误。正确的做法是 $a 这里应该加上双引号,否则 -n $a 的结果永远是 true:#!/bin/basha=""if [ -n "$a" ]thenecho "-n $a : 字符串长度不为 0"elseecho "-n $a : 字符串长度为 0"fi输出结果为:-n : 字符串长度为 0-------------------------------------------------------------------------文件测试运算符文件测试运算符用于检测 Unix 文件的各种属性。属性检测描述如下:操作符说明举例-b file检测文件是否是块设备文件,如果是,则返回 true。[ -b $file ] 返回 false。-c file检测文件是否是字符设备文件,如果是,则返回 true。[ -c $file ] 返回 false。-d file检测文件是否是目录,如果是,则返回 true。[ -d $file ] 返回 false。-f file检测文件是否是普通文件(既不是目录,也不是设备文件),如果是,则返回 true。[ -f $file ] 返回 true。-g file检测文件是否设置了 SGID 位,如果是,则返回 true。[ -g $file ] 返回 false。-k file检测文件是否设置了粘着位(Sticky Bit),如果是,则返回 true。[ -k $file ] 返回 false。-p file检测文件是否是有名管道,如果是,则返回 true。[ -p $file ] 返回 false。-u file检测文件是否设置了 SUID 位,如果是,则返回 true。[ -u $file ] 返回 false。-r file检测文件是否可读,如果是,则返回 true。[ -r $file ] 返回 true。-w file检测文件是否可写,如果是,则返回 true。[ -w $file ] 返回 true。-x file检测文件是否可执行,如果是,则返回 true。[ -x $file ] 返回 true。-s file检测文件是否为空(文件大小是否大于0),不为空返回 true。[ -s $file ] 返回 true。-e file检测文件(包括目录)是否存在,如果是,则返回 true。[ -e $file ] 返回 true。其他检查符:-S: 判断某文件是否 socket。-L: 检测文件是否存在并且是一个符号链接。实例变量 file 表示文件 /var/www/runoob/test.sh,它的大小为 100 字节,具有 rwx 权限。下面的代码,将检测该文件的各种属性:实例#!/bin/bash# author:菜鸟教程# url:www.runoob.comfile="/var/www/runoob/test.sh"if [ -r $file ]thenecho "文件可读"elseecho "文件不可读"fiif [ -w $file ]thenecho "文件可写"elseecho "文件不可写"fiif [ -x $file ]thenecho "文件可执行"elseecho "文件不可执行"fiif [ -f $file ]thenecho "文件为普通文件"elseecho "文件为特殊文件"fiif [ -d $file ]thenecho "文件是个目录"elseecho "文件不是个目录"fiif [ -s $file ]thenecho "文件不为空"elseecho "文件为空"fiif [ -e $file ]thenecho "文件存在"elseecho "文件不存在"fi执行脚本,输出结果如下所示:文件可读文件可写文件可执行文件为普通文件文件不是个目录文件不为空文件存在补充:if [ ! -d ${DIR} ]; then mkdir -p ${DIR}-z至-d意思:[ -a FILE ] 如果 FILE 存在则为真。[ -b FILE ] 如果 FILE 存在且是一个块特殊文件则为真。[ -c FILE ] 如果 FILE 存在且是一个字特殊文件则为真。[ -d FILE ] 如果 FILE 存在且是一个目录则为真。[ -e FILE ] 如果 FILE 存在则为真。[ -f FILE ] 如果 FILE 存在且是一个普通文件则为真。[ -g FILE ] 如果 FILE 存在且已经设置了SGID则为真。[ -h FILE ] 如果 FILE 存在且是一个符号连接则为真。[ -k FILE ] 如果 FILE 存在且已经设置了粘制位则为真。[ -p FILE ] 如果 FILE 存在且是一个名字管道(F如果O)则为真。[ -r FILE ] 如果 FILE 存在且是可读的则为真。[ -s FILE ] 如果 FILE 存在且大小不为0则为真。[ -t FD ] 如果文件描述符 FD 打开且指向一个终端则为真。[ -u FILE ] 如果 FILE 存在且设置了SUID (set user ID)则为真。[ -w FILE ] 如果 FILE 如果 FILE 存在且是可写的则为真。[ -x FILE ] 如果 FILE 存在且是可执行的则为真。[ -O FILE ] 如果 FILE 存在且属有效用户ID则为真。[ -G FILE ] 如果 FILE 存在且属有效用户组则为真。[ -L FILE ] 如果 FILE 存在且是一个符号连接则为真。[ -N FILE ] 如果 FILE 存在 and has been mod如果ied since it was last read则为真。[ -S FILE ] 如果 FILE 存在且是一个套接字则为真。[ FILE1 -nt FILE2 ] 如果 FILE1 has been changed more recently than FILE2, or 如果 FILE1 exists and FILE2 does not则为真。[ FILE1 -ot FILE2 ] 如果 FILE1 比 FILE2 要老, 或者 FILE2 存在且 FILE1 不存在则为真。[ FILE1 -ef FILE2 ] 如果 FILE1 和 FILE2 指向相同的设备和节点号则为真。[ -o OPTIONNAME ] 如果 shell选项 “OPTIONNAME” 开启则为真。[ -z STRING ] “STRING” 的长度为零则为真。[ -n STRING ] or [ STRING ] “STRING” 的长度为非零 non-zero则为真。[ STRING1 == STRING2 ] 如果2个字符串相同。 “=” may be used instead of “==” for strict POSIX compliance则为真。[ STRING1 != STRING2 ] 如果字符串不相等则为真。[ STRING1 < STRING2 ] 如果 “STRING1” sorts before “STRING2” lexicographically in the current locale则为真。[ STRING1 > STRING2 ] 如果 “STRING1” sorts after “STRING2” lexicographically in the current locale则为真。[ ARG1 OP ARG2 ] “OP” is one of -eq, -ne, -lt, -le, -gt or -ge. These arithmetic binary operators return true if “ARG1” is equal to, not equal to, less than, less than or equal to, greater than, or greater than or equal to “ARG2”, respectively. “ARG1” and “ARG2” are integers.------------------------------------------------------------------------使用 [[ ... ]] 条件判断结构,而不是 [ ... ],能够防止脚本中的许多逻辑错误。比如,&&、||、< 和 > 操作符能够正常存在于 [[ ]] 条件判断结构中,但是如果出现在 [ ] 结构中的话,会报错。------------------------------------------------------------------------