全国协议5人面授小班,企业级独立开发考核,转业者的IT软件工程师基地 登录/注册 | 如何报名
当前位置: 服务端相关   >  Shell 运算符
admin · 更新于 2021-08-06

1. Shell 运算符概述

1.1 Shell 运算符是什么

与其他语言一样,Shell 也有运算符,在 Shell 中其根据类型不同也有不少运算符分类,那么什么是运算符呢?例如大家都知道在算术运算中的加减乘除,+ 就是我们 Shell 中的算术运算符的一种,当然还有很多其他的功能各异的运算符,作为条件判断与算术操作等重要功能,构成了 Shell 中的基本元素。

1.2 为什么要用运算符

当我们对数值进行算术运算,当我们需要对文件进行判断,当我们需要多逻辑进行判断的时候,这些情况都需要使用不同类型的运算符,使得我们脚本更为灵活便捷。

2. Shell 运算符分类

我们知道了 shell 中运算符是什么及其功能,接下来让我们看一下 Shell 脚本运算符的分类及每种运算符的基本操作。

2.1 算术运算符

算术运算符顾名思义,其就是进行加减乘除数值运算,在 shell 中,bash 不支持原生的数学运算,需要利用第三方工具来如 letexpr 等来实现。

运算符说明举例
+加法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。

2.1.1 let

可以利用 let 对数值进行运算,let C=$A+$B, 例如:

[root@master ~]# A=1[root@master ~]# B=2[root@master ~]# let C=${A}+${B}[root@master ~]# echo $C3
代码块
  • 1
  • 2
  • 3
  • 4
  • 5

注意:let 运算后需要将其赋值给一个变量。

2.1.2 expr

可以利用 expr 对数组进行运算,C=$(expr $A+$B),例如:

[root@master ~]# C=`expr $A + $B`[root@master ~]# echo $C3
代码块
  • 1
  • 2
  • 3

注意 + 号两边需要有空格,不然会将其当作字符串连接

2.1.3 []

可以利用 [] 来对数值进行运算,C=[A+B],例如:

[root@master ~]# C=$[$A+$B][root@master ~]# echo $C3
代码块
  • 1
  • 2
  • 3

2.1.4 (())

利用 (()) 来对数值进行运算,C=$(($A+$B)),例如:

[root@master ~]# C=$(($A+$B))[root@master ~]# echo $C3
代码块
  • 1
  • 2
  • 3

2.2 关系运算符

了解了算术运算,接下来让我们学习关系运算。

比较符描述示例
-eq,equal等于[1 -eq 1] 为 true
-ne,not equal不等于[1 -ne 1] 为 false
-gt,greater than大于[2 -gt 1] 为 true
-lt,lesser than小于[2 -lt 1] 为 false
-ge,greater or equal大于或等于[2 -ge 1] 为 true
-le,lesser or equal小于或等于[2 -le 1] 为 false

关系运算顾名思义就是比较数字的大小,注意关系运算符作用的为数字,不能用其来比较字符串。

#!/bin/bashnum1=1num2=2echo "num1 为:${num1}"echo "num2 为:${num2}"if [ $num1 -eq $num2 ]then
   echo "$num1 -eq $num2 : num1 等于 num2"else
   echo "$num1 -eq $num2: num1 不等于 num2"fiif [ $num1 -ne $num2 ]then
   echo "$num1 -ne $num2: num1 不等于 num2"else
   echo "$num1 -ne $num2 : num1 等于 num2"fiif [ $num1 -gt $num2 ]then
   echo "$num1 -gt $num2: num1 大于 num2"else
   echo "$num1 -gt $num2: num1 不大于 num2"fiif [ $num1 -lt $num2 ]then
   echo "$num1 -lt $num2: num1 小于 num2"else
   echo "$num1 -lt $num2: num1 不小于 num2"fiif [ $num1 -ge $num2 ]then
   echo "$num1 -ge $num2: num1 大于或等于 num2"else
   echo "$num1 -ge $num2: num1 小于 num2"fiif [ $num1 -le $num2 ]then
   echo "$num1 -le $num2: num1 小于或等于 num2"else
   echo "$num1 -le $num2: num1 大于 num2"fi
代码块
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 25
  • 26
  • 27
  • 28
  • 29
  • 30
  • 31
  • 32
  • 33
  • 34
  • 35
  • 36
  • 37
  • 38
  • 39
  • 40
  • 41
  • 42
  • 43
  • 44

运行结果为:

num1 为:1num2 为:21 -eq 2: num1 不等于 num21 -ne 2: num1 不等于 num21 -gt 2: num1 不大于 num21 -lt 2: num1 小于 num21 -ge 2: num1 小于 num21 -le 2: num1 小于或等于 num2
代码块
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8

2.3 布尔运算符

布尔运算符也就是我们常说的与或非

运算符说明举例
-a与运算,两个表达式都为 true 才返回 true。[1 -lt 2 -a 10 -gt 2] 返回 true。
-o或运算,有一个表达式为 true 则返回 true。[1 -lt 2 -o 2 -gt 10] 返回 true。
!非运算,表达式为 true 则返回 false,否则返回 true。[! false] 返回 true。

例如:

#!/bin/bashnum1=10num2=20echo "num1 为: ${num1}"echo "num2 为: ${num2}"if [ $num1 -lt 40 -a $num2 -gt 15 ];then
   echo "$num1 小于 40 且 $num2 大于 15 : 返回 true"else
   echo "$num1 小于 40 且 $num2 大于 15 : 返回 fnum1lse"fi
echo "或运算"if [ $num1 -lt 40 -o $num2 -gt 40 ];then
   echo "$num1 小于 40 或 $num2 大于 40 : 返回 true"else
   echo "$num1 小于 40 或 $num2 大于 40 : 返回 fnum1lse"fi

echo "非运算"if [ $num1 != $num2 ];then
   echo "$num1 != $num2 : num1 不等于 num2"else
   echo "$num1 != $num2: num1 等于 num2"fi
代码块
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24

返回结果为:

num1 为: 10num2 为: 2010 小于 4020 大于 15 : 返回 true或运算10 小于 4020 大于 40 : 返回 true非运算10 != 20 : num1 不等于 num2[root@master scripts]# vim 2.sh [root@master scripts]# bash 2.sh num1 为: 10num2 为: 2010 小于 4020 大于 15 : 返回 true或运算10 小于 4020 大于 40 : 返回 true非运算10 != 20 : num1 不等于 num2		
代码块
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16

2.4 逻辑运算符

逻辑运算符为,以下介绍 Shell 的逻辑运算符,假定变量 A 为 1,变量 b 为 2:

运算符说明举例
&&逻辑的 AND[[ $A -lt 10 && $B -gt 100 ]] 返回 false
||逻辑的 OR[[ $A -lt 10 || $B -gt 100 ]] 返回 true

例如:

#!/bin/bashnum1=1num2=2echo "num1 为:${num1}"echo "num2 为:${num2}"if [[ $num1 -lt 5 && $num2 -gt 5 ]];then
   echo "返回 true"else
   echo "返回 false"fiif [[ $num1 -lt 5 || $num2 -gt 5 ]];then
   echo "返回 true"else
   echo "返回 false"fi
代码块
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19

返回:

num1 为:1num2 为:2返回 false返回 true
代码块
  • 1
  • 2
  • 3
  • 4

2.5 字符串运算符

对于字符串进行一些判断操作,假定变量 a 为 “linux”,变量 b 为 “shell”:

运算符说明举例
=检测两个字符串是否相等,相等返回 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/bashstr1="linux"str2="shell"echo "str1 为:${str1}"echo "str2 为:${str2}"if [ $str1 = $str2 ];then
   echo "$str1 = $str2 : str1 等于 str2"else
   echo "$str1 = $str2: str1 不等于 str2"fiif [ $str1 != $str2 ];then
   echo "$str1 != $str2 : str1 不等于 str2"else
   echo "$str1 != $str2: str1 等于 str2"fiif [ -z $str1 ];then
   echo "-z $str1 : 字符串长度为 0"else
   echo "-z $str1 : 字符串长度不为 0"fiif [ -n "$str1" ];then
   echo "-n $str1 : 字符串长度不为 0"else
   echo "-n $str1 : 字符串长度为 0"fiif [ ${str1} ];then
   echo "str1 : 字符串不为空"else
   echo "str1 : 字符串为空"fi
代码块
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 25
  • 26
  • 27
  • 28
  • 29
  • 30
  • 31
  • 32
  • 33
  • 34

返回为:

str1 为:linux
str2 为:shell
linux = shell: str1 不等于 str2
linux != shell : str1 不等于 str2-z linux : 字符串长度不为 0-n linux : 字符串长度不为 0str1 : 字符串不为空	
代码块
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7

2.6 文件测试运算符

文件测试在我们编写 shell 中与文件操作非常常用,熟练掌握文件操作可以在后续的 shell 编写中得心应手,例如 file 变量为:

操作符说明举例
-dfile 检测文件是否是目录,如果是,则返回 true。[-d $file] 返回 false。
-ffile 检测文件是否是普通文件(既不是目录,也不是设备文件),如果是,则返回 true。[-f $file] 返回 true。
-cfile 检测文件是否是字符设备文件,如果是,则返回 true。[-c $file] 返回 false。
-bfile 检测文件是否是块设备文件,如果是,则返回 true。[-b $file] 返回 false。
-gfile 检测文件是否设置了 SGID 位,如果是,则返回 true。[-g $file] 返回 false。
-ufile 检测文件是否设置了 SUID 位,如果是,则返回 true。[-u $file] 返回 false。
-kfile 检测文件是否设置了粘着位 (Sticky Bit),如果是,则返回 true。[-k $file] 返回 false。
-pfile 检测文件是否是有名管道,如果是,则返回 true。[-p $file] 返回 false。
-rfile 检测文件是否可读,如果是,则返回 true。[-r $file] 返回 true。
-wfile 检测文件是否可写,如果是,则返回 true。[-w $file] 返回 true。
-xfile 检测文件是否可执行,如果是,则返回 true。[-x $file] 返回 true。
-sfile 检测文件是否为空(文件大小是否大于 0),不为空返回 true。[-s $file] 返回 true。
-efile 检测文件(包括目录)是否存在,如果是,则返回 true。[-e $file] 返回 true。

例如:

#!/bin/bash

TEST_FILE="/etc/fstab"
echo "检测的文件为:${TEST_FILE}"
echo "文件信息为:$(ls -l ${TEST_FILE})"


if [ -r $TEST_FILE ]
then
   echo "文件可读"
else
   echo "文件不可读"
fi
if [ -w $TEST_FILE ]
then
   echo "文件可写"
else
   echo "文件不可写"
fi
if [ -x $TEST_FILE ]
then
   echo "文件可执行"
else
   echo "文件不可执行"
fi
if [ -f $TEST_FILE ]
then
   echo "文件为普通文件"
else
   echo "文件为特殊文件"
fi
if [ -d $TEST_FILE ]
then
   echo "文件是个目录"
else
   echo "文件不是个目录"
fi
if [ -s $TEST_FILE ]
then
   echo "文件不为空"
else
   echo "文件为空"
fi
if [ -e $TEST_FILE ]
then
   echo "文件存在"
else
   echo "文件不存在"
fi
代码块
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 25
  • 26
  • 27
  • 28
  • 29
  • 30
  • 31
  • 32
  • 33
  • 34
  • 35
  • 36
  • 37
  • 38
  • 39
  • 40
  • 41
  • 42
  • 43
  • 44
  • 45
  • 46
  • 47
  • 48
  • 49

返回为:

检测的文件为:/etc/fstab
文件信息为:-rw-r--r--. 1 root root 500 Jan 17 14:23 /etc/fstab
文件可读
文件可写
文件不可执行
文件为普通文件
文件不是个目录
文件不为空
文件存在
代码块
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9

3. 实例

3.1 需求

编写一个脚本,传入一个 linux 文件系统的路径,判断其下面文件及目录的数量。

3.2 思路

可以利用文件测试运算符来判断输出的目录是否正确,之后利用算术运算符配合数组对文件或目录进行统计。

3.3 实现

#!/bin/bash# Description: count file scripts# Auth: kaliarch# Email: kaliarch@163.com# function: count file# Date: 2020-03-08 14:00# Version: 1.0# 判断输入参数[ $# -ne 1 ] && echo "输入参数错误,${0} check_dir" && exit 1# 判断输入的是否为存在的目录,不存在则退出CHECK_DIR=$1[ ! -d ${CHECK_DIR} ] && echo "检测系统不存在目录:${CHECK_DIR}, 请输入正确的目录" && exit 1# 对目录下的文件进行统计DIR_NUM=0
FILE_NUM=0
OTHER_NUM=0for item in ${CHECK_DIR}/*do
        if [ -d ${item} ];then
                # 如果为目录,则目录总数加一
                DIR_NUM=$((${DIR_NUM}+1))
        elif [ -f ${item} ];then
                FILE_NUM=$((${FILE_NUM}+1))
        else
                OTHER_NUM=$((${OTHER_NUM}+1))
        fidoneecho "检测目录为:${CHECK_DIR}"echo "文件类型数量为:${FILE_NUM}"echo "目录类型数量为:${DIR_NUM}"echo "其他类型数量为:${OTHER_NUM}"[root@master scripts]# bash count_file.sh 输入参数错误,count_file.sh check_dir[root@master scripts]# bash count_file.sh aaaa检测系统不存在目录:aaaa, 请输入正确的目录[root@master scripts]# bash count_file.sh /tmptmptmp检测系统不存在目录:/tmptmptmp, 请输入正确的目录[root@master scripts]# bash count_file.sh /检测目录为:/
文件类型数量为:0
目录类型数量为:23
其他类型数量为:0[root@master scripts]# bash count_file.sh /root检测目录为:/root
文件类型数量为:8
目录类型数量为:5
其他类型数量为:0[root@master scripts]# bash count_file.sh /dev/检测目录为:/dev/
文件类型数量为:1
目录类型数量为:19
其他类型数量为:139
代码块
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 25
  • 26
  • 27
  • 28
  • 29
  • 30
  • 31
  • 32
  • 33
  • 34
  • 35
  • 36
  • 37
  • 38
  • 39
  • 40
  • 41
  • 42
  • 43
  • 44
  • 45
  • 46
  • 47
  • 48
  • 49
  • 50
  • 51
  • 52
  • 53
  • 54
  • 55
  • 56
  • 57
  • 58
  • 59
  • 60
  • 61

当我们不输入任何参数的时候,提示需要输入一个路径参数,输入了文件名称或不存在的路径时,文件测试运算符判断输入异常,不是一个有效的文件目录。

当我们输入正常的目录时,即可获得正确的目录或文件数。

4. 注意事项

  • 对于算术运算,大家可以根据具体场景和环境来选择,例如系统内没有计算工具等,可以优先选择 [] 和 (()) 来进行,也可以根据自己喜好选择;
  • 对于关系运算,比较的数字,不是字符串,一定要牢记这个注意点,对于字符串判断可以用字符串运算符;
  • 对于布尔运算和逻辑运算其实是一个东西,只不过布尔运算符有一个非运算,可以进行灵活运用;
  • 文件测试符常用与判断 linux 系统文件的操作,在后期 shell 编程可谓举足轻重,牢记每个文件运算符会使得后期编程得心应手。

5. 小结

运算符可谓 Shell 脚本的灵魂,后期我们的循环和判断里面的条件都是这些运算符构成,它是流程框架的基础,熟练掌握运算符的分类及每个的用法,通过动手实践区分其特征,举一反三灵活运用。


为什么选择汉码未来