一、条件判断语法结构

思考:何为真(true)?何为假(false)?

1. 条件判断语法格式

  • 格式1: test 条件表达式
  • 格式2: [ 条件表达式 ]
  • 格式3: [[ 条件表达式 ]] 支持正则 =~

特别说明:

1)[ 亲亲,我两边都有空格,不空打死你呦 ] 条件判断和流程控制 - 图1

2)[[ 亲亲,我两边都有空格,不空打死你呦 ]]条件判断和流程控制 - 图2

2. 条件判断相关参数

问:你要判断什么?

答:我要判断文件类型,判断文件新旧,判断字符串是否相等,判断权限等等…

㈠ 判断文件类型

判断参数 含义
-e 判断文件是否存在(任何类型文件)
-f 判断文件是否存在并且是一个普通文件
-d 判断文件是否存在并且是一个目录
-L 判断文件是否存在并且是一个软连接文件
-b 判断文件是否存在并且是一个块设备文件
-S 判断文件是否存在并且是一个套接字文件
-c 判断文件是否存在并且是一个字符设备文件
-p 判断文件是否存在并且是一个命名管道文件
-s 判断文件是否存在并且是一个非空文件(有内容)

举例说明:

  1. test -e file 只要文件存在条件为真
  2. [ -d /shell01/dir1 ] 判断目录是否存在,存在条件为真
  3. [ ! -d /shell01/dir1 ] 判断目录是否存在,不存在条件为真
  4. [[ -f /shell01/1.sh ]] 判断文件是否存在,并且是一个普通的文件

㈡ 判断文件权限

判断参数 含义
-r 当前用户对其是否可读
-w 当前用户对其是否可写
-x 当前用户对其是否可执行
-u 是否有suid,高级权限冒险位
-g 是否sgid,高级权限强制位
-k 是否有t位,高级权限粘滞位

㈢ 判断文件新旧

说明:这里的新旧指的是文件的修改时间。

判断参数 含义
file1 -nt file2 比较file1是否比file2新
file1 -ot file2 比较file1是否比file2旧
file1 -ef file2 比较是否为同一个文件,或者用于判断硬连接,是否指向同一个inode

㈣ 判断整数

判断参数 含义
-eq 相等
-ne 不等
-gt 大于
-lt 小于
-ge 大于等于
-le 小于等于

㈤ 判断字符串

判断参数 含义
-z 判断是否为空字符串,字符串长度为0则成立
-n 判断是否为非空字符串,字符串长度不为0则成立
string1 = string2 判断字符串是否相等
string1 != string2 判断字符串是否相不等
string1 =~ string2 判断string1 是否包含string2

㈥ 多重条件判断

判断符号 含义 举例
-a 和 && 逻辑与 [ 1 -eq 1 -a 1 -ne 0 ] [ 1 -eq 1 ] && [ 1 -ne 0 ]
-o 和 || 逻辑或 [ 1 -eq 1 -o 1 -ne 1 ]

特别说明:

&& 前面的表达式为真,才会执行后面的代码

|| 前面的表达式为假,才会执行后面的代码

; 只用于分割命令或表达式

① 举例说明

  • 数值比较
  1. [root@server ~]# [ $(id -u) -eq 0 ] && echo "the user is admin"
  2. [root@server ~]$ [ $(id -u) -ne 0 ] && echo "the user is not admin"
  3. [root@server ~]$ [ $(id -u) -eq 0 ] && echo "the user is admin" || echo "the user is not admin"
  4. [root@server ~]# uid=`id -u`
  5. [root@server ~]# test $uid -eq 0 && echo this is admin
  6. this is admin
  7. [root@server ~]# [ $(id -u) -ne 0 ] || echo this is admin
  8. this is admin
  9. [root@server ~]# [ $(id -u) -eq 0 ] && echo this is admin || echo this is not admin
  10. this is admin
  11. [root@server ~]# su - stu1
  12. [stu1@server ~]$ [ $(id -u) -eq 0 ] && echo this is admin || echo this is not admin
  13. this is not admin
  • 类C风格的数值比较
  1. 注意:在(( ))中,=表示赋值;==表示判断
  2. [root@server ~]# ((1==2));echo $?
  3. [root@server ~]# ((1<2));echo $?
  4. [root@server ~]# ((2>=1));echo $?
  5. [root@server ~]# ((2!=1));echo $?
  6. [root@server ~]# ((`id -u`==0));echo $?
  7. [root@server ~]# ((a=123));echo $a
  8. [root@server ~]# unset a
  9. [root@server ~]# ((a==123));echo $?
  • 字符串比较
  1. 注意:双引号引起来,看作一个整体;= == [ 字符串 ] 比较中都表示判断
  2. [root@server ~]# a='hello world';b=world
  3. [root@server ~]# [ $a = $b ];echo $?
  4. [root@server ~]# [ "$a" = "$b" ];echo $?
  5. [root@server ~]# [ "$a" != "$b" ];echo $?
  6. [root@server ~]# [ "$a" !== "$b" ];echo $? 错误
  7. [root@server ~]# [ "$a" == "$b" ];echo $?
  8. [root@server ~]# test "$a" != "$b";echo $?
  9. test 表达式
  10. [ 表达式 ]
  11. [[ 表达式 ]]
  12. 思考:[ ] [[ ]] 有什么区别?
  13. [[ ]] 相当于给所有的$变量加了“”
  14. [root@server ~]# a=
  15. [root@server ~]# test -z $a;echo $?
  16. [root@server ~]# a=hello
  17. [root@server ~]# test -z $a;echo $?
  18. [root@server ~]# test -n $a;echo $?
  19. [root@server ~]# test -n "$a";echo $?
  20. a=
  21. # [ '' = $a ];echo $?
  22. -bash: [: : unary operator expected
  23. 2
  24. # [[ '' = $a ]];echo $?
  25. 0
  26. [root@server ~]# [ 1 -eq 0 -a 1 -ne 0 ];echo $?
  27. [root@server ~]# [ 1 -eq 0 && 1 -ne 0 ];echo $?
  28. [root@server ~]# [[ 1 -eq 0 && 1 -ne 0 ]];echo $?

② 逻辑运算符总结

  1. 符号;和&&和||都可以用来分割命令或者表达式
  2. 分号(;)完全不考虑前面的语句是否正确执行,都会执行;号后面的内容
  3. &&符号,需要考虑&&前面的语句的正确性,前面语句正确执行才会执行&&后的内容;反之亦然
  4. ||符号,需要考虑||前面的语句的非正确性,前面语句执行错误才会执行||后内容;反之亦然
  5. 如果&&和||一起出现,从左往右依次看,按照以上原则

    3. 更多判断,man test去查看,很多的参数都用来进行条件判断

    二、流程控制语句

关键词:选择(人生漫漫长路,我该何去何从条件判断和流程控制 - 图3

: :表示什么都不做类似于python 中的pass

1. 基本语法结构

㈠ if结构

箴言1:只要正确,就要一直向前冲条件判断和流程控制 - 图4

F:表示false,为假

T:表示true,为真

  1. if [ condition ];then
  2. command
  3. command
  4. fi
  5. if test 条件;then
  6. 命令
  7. fi
  8. if [[ 条件 ]];then
  9. 命令
  10. fi
  11. [ 条件 ] && command

条件判断和流程控制 - 图5

㈡ if…else结构

箴言2:分叉路口,二选一

  1. if [ condition ];then
  2. command1
  3. else
  4. command2
  5. fi
  6. [ 条件 ] && command1 || command2

条件判断和流程控制 - 图6

小试牛刀:

让用户自己输入字符串,如果用户输入的是hello,请打印world,否则打印“请输入hello”

  1. read定义变量
  2. if….else…
  1. #!/bin/env bash
  2. read -p '请输入一个字符串:' str
  3. if [ "$str" = 'hello' ];then
  4. echo 'world'
  5. else
  6. echo '请输入hello!'
  7. fi
  8. 1 #!/bin/env bash
  9. 2
  10. 3 read -p "请输入一个字符串:" str
  11. 4 if [ "$str" = "hello" ]
  12. 5 then
  13. 6 echo world
  14. 7 else
  15. 8 echo "请输入hello!"
  16. 9 fi
  17. echo "该脚本需要传递参数"
  18. 1 if [ $1 = hello ];then
  19. 2 echo "hello"
  20. 3 else
  21. 4 echo "请输入hello"
  22. 5 fi
  23. #!/bin/env bash
  24. A=hello
  25. B=world
  26. C=hello
  27. if [ "$1" = "$A" ];then
  28. echo "$B"
  29. else
  30. echo "$C"
  31. fi
  32. read -p '请输入一个字符串:' str;
  33. [ "$str" = 'hello' ] && echo 'world' || echo '请输入hello!'

㈢ if…elif…else结构

箴言3:选择很多,能走的只有一条

  1. if [ condition1 ];then
  2. command1 结束
  3. elif [ condition2 ];then
  4. command2 结束
  5. else
  6. command3
  7. fi
  8. 注释:
  9. 如果条件1满足,执行命令1后结束;如果条件1不满足,再看条件2,如果条件2满足执行命令2后结束;如果条件1和条件2都不满足执行命令3结束.

条件判断和流程控制 - 图7

㈣ 层层嵌套结构

箴言4:多次判断,带你走出人生迷雾。

  1. if [ condition1 ];then
  2. command1
  3. if [ condition2 ];then
  4. command2
  5. fi
  6. else
  7. if [ condition3 ];then
  8. command3
  9. elif [ condition4 ];then
  10. command4
  11. else
  12. command5
  13. fi
  14. fi
  15. 注释:
  16. 如果条件1满足,执行命令1;如果条件2也满足执行命令2,如果不满足就只执行命令1结束;
  17. 如果条件1不满足,不看条件2;直接看条件3,如果条件3满足执行命令3;如果不满足则看条件4,如果条件4满足执行命令4;否则执行命令5

条件判断和流程控制 - 图8

2. 应用案例

㈠ 判断两台主机是否ping通

需求:判断当前主机是否和远程主机是否ping通

① 思路

  1. 使用哪个命令实现 ping -c次数
  2. 根据命令的执行结果状态来判断是否通$?
  3. 根据逻辑和语法结构来编写脚本(条件判断或者流程控制)

② 落地实现

  1. #!/bin/env bash
  2. # 该脚本用于判断当前主机是否和远程指定主机互通
  3. # 交互式定义变量,让用户自己决定ping哪个主机
  4. read -p "请输入你要ping的主机的IP:" ip
  5. # 使用ping程序判断主机是否互通
  6. ping -c1 $ip &>/dev/null
  7. if [ $? -eq 0 ];then
  8. echo "当前主机和远程主机$ip是互通的"
  9. else
  10. echo "当前主机和远程主机$ip不通的"
  11. fi
  12. 逻辑运算符
  13. test $? -eq 0 && echo "当前主机和远程主机$ip是互通的" || echo "当前主机和远程主机$ip不通的"

㈡ 判断一个进程是否存在

需求:判断web服务器中httpd进程是否存在

① 思路

  1. 查看进程的相关命令 ps pgrep
  2. 根据命令的返回状态值来判断进程是否存在
  3. 根据逻辑用脚本语言实现

② 落地实现

  1. #!/bin/env bash
  2. # 判断一个程序(httpd)的进程是否存在
  3. pgrep httpd &>/dev/null
  4. if [ $? -ne 0 ];then
  5. echo "当前httpd进程不存在"
  6. else
  7. echo "当前httpd进程存在"
  8. fi
  9. 或者
  10. test $? -eq 0 && echo "当前httpd进程存在" || echo "当前httpd进程不存在"

③ 补充命令

  1. pgrep命令:以名称为依据从运行进程队列中查找进程,并显示查找到的进程id
  2. 选项
  3. -o:仅显示找到的最小(起始)进程号;
  4. -n:仅显示找到的最大(结束)进程号;
  5. -l:显示进程名称;
  6. -P:指定父进程号;pgrep -p 4764 查看父进程下的子进程id
  7. -g:指定进程组;
  8. -t:指定开启进程的终端;
  9. -u:指定进程的有效用户ID

㈢ 判断一个服务是否正常

需求:判断门户网站是否能够正常访问

① 思路

  1. 可以判断进程是否存在,用/etc/init.d/httpd status判断状态等方法
  2. 最好的方法是直接去访问一下,通过访问成功和失败的返回值来判断
    • Linux环境,wget curl elinks -dump

② 落地实现

  1. #!/bin/env bash
  2. # 判断门户网站是否能够正常提供服务
  3. #定义变量
  4. web_server=www.itcast.cn
  5. #访问网站
  6. wget -P /shell/ $web_server &>/dev/null
  7. [ $? -eq 0 ] && echo "当前网站服务是ok" && rm -f /shell/index.* || echo "当前网站服务不ok,请立刻处理"

3. 课堂练习

㈠ 判断用户是否存在

需求1:输入一个用户,用脚本判断该用户是否存在

  1. #!/bin/env bash
  2. 2 read -p "请输入一个用户名:" user_name
  3. 3 id $user_name &>/dev/null
  4. 4 if [ $? -eq 0 ];then
  5. 6 echo "该用户存在!"
  6. 7 else
  7. 8 echo "用户不存在!"
  8. 9 fi
  9. #!/bin/bash
  10. # 判断 用户(id) 是否存在
  11. read -p "输入壹个用户:" id
  12. id $id &> /dev/null
  13. if [ $? -eq 0 ];then
  14. echo "该用户存在"
  15. else
  16. echo "该用户不存在"
  17. fi
  18. #!/bin/env bash
  19. read -p "请输入你要查询的用户名:" username
  20. grep -w $username /etc/passwd &>/dev/null
  21. if [ $? -eq 0 ]
  22. then
  23. echo "该用户已存在"
  24. else
  25. echo "该用户不存在"
  26. fi
  27. #!/bin/bash
  28. read -p "请输入你要检查的用户名:" name
  29. id $name &>/dev/null
  30. if [ $? -eq 0 ]
  31. then
  32. echo 用户"$name"已经存在
  33. else
  34. echo 用户"$name"不存在
  35. fi
  36. #!/bin/env bash
  37. #判断用户是否存在
  38. read -p "请写出用户名" id
  39. id $id
  40. if [ $? -eq 0 ];then
  41. echo "用户存在"
  42. else
  43. echo "用户不存在"
  44. fi
  45. #!/bin/env bash
  46. read -p '请输入用户名:' username
  47. id $username &>/dev/null
  48. [ $? -eq 0 ] && echo '用户存在' || echo '不存在'

㈡ 判断软件包是否安装

需求2:用脚本判断一个软件包是否安装,如果没安装则安装它(假设本地yum已配置)

  1. rpm -qa | grep 软件包名
  2. 已经安装$?为0未安装$?未1

㈢ 判断当前主机的内核版本

需求3:判断当前内核主版本是否为2,且次版本是否大于等于6;如果都满足则输出当前内核版本

  1. 思路:
  2. 1. 先查看内核的版本号 uname -r
  3. 2. 先将内核的版本号保存到一个变量里,然后再根据需求截取出该变量的一部分:主版本和次版本
  4. 3. 根据需求进步判断
  5. #!/bin/bash
  6. kernel=`uname -r`
  7. var1=`echo $kernel|cut -d. -f1`
  8. var2=`echo $kernel|cut -d. -f2`
  9. test $var1 -eq 2 -a $var2 -ge 6 && echo $kernel || echo "当前内核版本不符合要求"
  10. 或者
  11. [ $var1 -eq 2 -a $var2 -ge 6 ] && echo $kernel || echo "当前内核版本不符合要求"
  12. 或者
  13. [[ $var1 -eq 2 && $var2 -ge 6 ]] && echo $kernel || echo "当前内核版本不符合要求"
  14. 或者
  15. #!/bin/bash
  16. kernel=`uname -r`
  17. test ${kernel:0:1} -eq 2 -a ${kernel:2:1} -ge 6 && echo $kernel || echo '不符合要求'
  18. 其他命令参考:
  19. uname -r|grep ^2.[6-9] || echo '不符合要求'