条件语句与运算

概述

参考:

使用运算符操作一个或多个内容,然后得到另一个内容,这个过程就是运算。要操作的内容可以是一个具体的数值、字符串、变量等。

在编程中使用运算可以得到一个具体的值,或者进行一次判断以得出“真”或者“假”的结果,以这个结果作为执行某些操作的依据。

EXAMPLE:

  • 2+3,进行算数运算,求和。2 和 3 是两个内容,+是运算符,运算后的值为 5。

  • [ test1 = test2 ],进行判断运算,判断运算符两边的内容是否一样,并得出“是”或者“否”这两种结论其中一个。test1 与 test2 是两个内容,=是运算符,运算后的结果是假,i.e.test1 不等于 test2。一般情况,当结果为真或者假之后,就可以执行某些操作,详见 3.Shell 控制结构.note

  • 判断命令运行结果:shell 中的 if 语句会运行“条件语句”中给定的命令,如果该命令的退出状态码(详见下文红字)是 0,则“分支”中给定的命令就会被执行。如果该命令的退出状态码非 0,则“分支”中给定的命令不被执行,且会继续执行该脚本中下一个命令。

    • 比如下面这种
      • if ! COMMAND; then echo “command failed”; exit 1; fi
  • 使用 test 命令进行判断:“条件语句”中除了运行命令判断退出状态码,还可以通过 test 命令来进行运算判断,然后通过运算结果得出状态码是 0 还是 1 来进行条件判断(e.g.1 是否大于 2,文件是否存在,字符串是否一样等运算)。当运算结果为真时退出码为 0,否则运算结果非假则退出码非 0。运算方式以及命令详见下文的运算

    • 语法结构:test CONDITION
      • EXAMPLE
        • test 1 -gt 2 # 判断 1 是否大于 2,使用 echo $?输出结果为 1,表示判断结果为错误,非 0
    • 在 shell 中,test 命令可以通过 [ 条件 ] 与 [[ 条件 ]] 来进行表示(e.g.[[ 1 -gt 2 ]]) 。这种表示方式与使用 test 命令效果相同

其实上述两种,说白了,都是判断命令运行结果,因为[[ ]]符号也相当于命令,判断括号中的内容执行是否成功。所以,在日常使用中,第一种判断命令运行结果,也经常放在[[ ]]来执行,比如 if \[\[ $(ls | grep test) ]]; then echo "搜到了"; fi 这种

注意:linux 命令执行完成后一共有两个输出内容

  • 命令执行结果:当命令执行完成后直接看到的屏幕输出的内容就是执行结果,
  • 命令执行状态:命令执行完成后还有有一个执行状态值,表示该命令是否执行成功,以及失败的状态值。该值是隐藏的,命令执行完成后不会显示该值,可以通过 echo $?查看。命令状态值可以通过脚本中命令 exit 来定义,以下是命令状态值的两种分类
  • 0:数字 0 表示执行状态成功,命令正确,条件判断为真
  • 非 0:表示命令执行失败,会返回非 0 的值,不同的值表示不同的失败问题,条件判断为假
  • 条件语句中只有一种判断方法:判断该命令执行的状态返回值,0 为真,非 0 为假,即返回值为 0 时,执行分支 1 语句,返回值为非 0 时执行分支 2 语句

注意:[[ ]] 中的语句是会真实执行的,并且一个完整的控制结构中,不管判断中的语句是否执行成功,其返回值都是 0,因为这个控制结构代码成功了。

[root@master ~]# if [[ $(mkdir test) ]]; then echo ok;fi
ok
[root@master ~]# if [[ $(mkdir test) ]]; then echo ok;fi
mkdir: cannot create directory ‘test’: File exists
[root@master ~]# echo $?
0

运算

按照运算所得结果来分类的话,总共分为两大类:

  • Boolean Operators(逻辑运算) # 之所以被称为逻辑运算符是因为它们的运算结果总是为布尔值 bool,不是 true 就是 false。e.g.1 是否等于 2、语句是否执行成功、是否有返回值、条件一成立且条件二失败结果四 true 还是 false
  • Arithmetic Operators(算数运算) # 最后的运算结果必然是数学概念上的整数、小数等。e.g.1+2=3、2*3=6 等
  • Relational Operators(关系运算)
  • String Operators(字符串运算)
  • File Test Operators(文件测试运算)

算术运算符

下表列出了常用的算术运算符,假定变量 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 ]。

  • 算数运算
    • if (( 1 + 2 == 3 )); then….. # 如果 1+2 等于 3,那么执行后面的语句

算数运算的相关命令

expr Expression

Expression(表达式) 为数值 算数运算符 数值

EXAMPLE

  • expr 3 + 7 # 输出结果为 10

VarName=$[算术表达式]

VarName=$((算术表达式))

let 命令

let VarName=算数表达式 && echo $VarName

EXAMPLE

  • let sum=3+8; echo $sum # 输出结果为 11

$[ ]$(( )) 符号

EXAMPLE

  • echo $[1+2] # 输出结果为 3

布尔运算符

逻辑运算符,有的地方也称为 Boolean(布尔) 运算符,假定变量 a 为 10,变量 b 为 20:

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

Syntax(语法)

逻辑运算(布尔运算,只有真,假两种) # (即条件语句的是否执行成功,成功为真,不成功为假,非真)

  • 与运算:&& (或者用-a)(条件一$$条件二=结果)
    • 真&&真=真
    • 真&&假=假
    • 假&&假=假
      • 条件一为假,结果即为假,条件二就不会执行
      • 条件一为真,则最终结果无法判断,那么条件二必须执行
  • 或运算:|| (或者用-o)(条件一||条件二=结果)
    • 真||真=真
    • 真||假=真
    • 假||假=假
      • 第一个条件为真,结果即为真
      • 条件一为真,结果即为真,条件二不会执行
      • 条件一为假,结果无法判断,那么条件二必须执行
  • 非运算:!
    • !真=假
    • !假=真
  • EXAMP LE:
    • id $name &> /dev/null && echo “exist” || echo “not exist” # 如果 id $name 结果为真,那么输出 exist 否则输出 not exist,因为与运算优先级更高,先判断 命令执行状态是否为真,如果为真,则必须执行第二条,如果为假,那么第二条不会执行,就直接进行或运算,第一条命令状态为假的话,就必须执行或运算中的第二条命令,即总体的第三条。

关系运算符

在编程领域中

  • 真 可以用 true 或者 1 来表示
  • 假 可以用 false 或者 0 来表示

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

下表列出了常用的关系运算符,假定变量 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。

Syntax(语法)

**[ NUM1 比较符 NUM2 ] **# num1 与 num2 为具体数字,注意括号中的空格不要忘了

  • 比较符说明:
    • -gt # 大于
    • -lt # 小于
    • -ge # 大于等于
    • -le # 小于等于
    • -ne # 不等于
    • -eq # 等于
  • EXAMPLE
    • [ 1 -ge 2 ] # 判断 1 是否大于 2,如果成功$?返回值为0,否则返回值为1,该命令$?的值为 1

字符串运算符

下表列出了常用的字符串运算符,假定变量 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。
STR检测字符串 STR 是否为空,不为空返回 true。等效于 -n[ $a ] 返回 true。

Syntax(语法)

[ str1 比较符 str2 ] # str1,str2 为具体字符串,注意写括号中的空格

  • 比较符:
    • == 是否等于
    • != 是否不等于
    • =~ 判定左侧的字符串能否被右侧的模式所匹配,通常只在[[]]中使用
    • < 是否小于
    • 是否大于(注意:大于小于号前需要加,否则脚本当成重定向符号)

    • [ -n str ] 检查 str 的长度是否非 0
    • [ -z str ] 检查 str 的长度是否为 0
  • EXAMPLE

文件测试运算符

文件测试运算符用于检测 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。

运算符按照操作格式分类:

  • 一元运算符:就是只需要一个操作数,如 a–、a++、 !a、 ~a 等
  • 二元运算符:就是需要两个操作数才能完成运算 如典型的 a+b、 a-b、 a*b、 a/b 等
  • 三元运算符::?唯一一个三元运算符

Syntax(语法)

**[ FileTestOperator “FILENAME” ] **# 为了防止文件名 FILENAME 中出现空格等特殊字符,所以用双引号引起来以防出现意外

  • **FileTestOperator # **所有选项检查前提都是含有隐含意义,就是默认先检查是否存在再检查其余特殊情况
    • -e # 检查文件是否存在
    • -d # 检查文件是否存在且为目录
    • -f # 检查是否为文件
    • -n # 是否为数字
    • -r(w)(x) # 检查是否可读(写)(执行)
    • -s # 检查是否为空
    • -O # 是否属于当前用户
    • -G # 是否默认组与当前用户相同
    • [ FILE1 -nt FILE ] 检查文件 1 是否新于文件 2
    • [ FILE1 -ot FILE2 ] 检查文件 1 是否旧于文件 2
  • EXAMPLE
    • if [ ! -f file.txt ] 如果 file.txt 存在且为文件