Shell条件测试

结构化命令概念

Shell按照命令在脚本中出现的顺序依次进行处理。对顺序操作来说,这已经足够了,因为在这种操作环境下,你想要的就是所有的命令按照正确的顺序执行。

许多程序要求对shell脚本中的命令施加一些逻辑流程控制。有一类命令会根据条件使脚本跳过某些命令。这样的命令通常称为结构化命令(structured command)

常见的条件测试命令: if-then语句case语句for语句while语句

if条件语句

语法结构

if单分支语句

if条件语句通常由以下三个关键字组成:

  1. if:用于指定要测试的条件
  2. then:用于指定如果条件为true时要执行的指令
  3. else:用于指定如果条件为false时要执行的指令
if condition
then
command1 
command2
...
commandN 
fi

在其他编程语言中,if语句之后的对象是一个等式,这个等式的求值结果为TRUE或FALSE。但bash shell的if语句并不是这么做的。bash shell的if语句会运行if后面的那个命令。如果该命令的退出状态码是0(该命令成功运行),位于then部分的命令就会被执行。如果该命令的退出状态码是其他值,then部分的命令就不会被执行,bash shell会继续执行脚本中的下一个命令。fi语句用来表示if-then语句到此结束。

创建脚本test.sh、编辑以下内容:

#!/bin/bash

# 测试的条件为`pwd`命令,根据命令的返回值进行跳转
if pwd
then
        echo "[提示] pwd 命令执行成功,已进入对应目录。"
fi

运行脚本:

[root@host1 ~]# bash test.sh
/home/centos
[提示] pwd 命令执行成功,已进入对应目录。

常见的退出状态码:

1711544029758.png

if-then 语句的另一种形式

if command; then
commands
fi

if-then-else 双分支语句

当if语句中的命令返回退出状态码0时,then部分中的命令会被执行,这跟普通的if-then
语句一样。当if语句中的命令返回非零退出状态码时,bash shell会执行else部分中的命令。

在test.sh文件的基础上添加else语句

#!/bin/bash

# 待测试的用户名为ubuntu
testuser=ubuntu

# 此时grep命令没有找到ubuntu字符,if语句跳转到else分支
if grep $testuser /etc/passwd
then
        echo "[成功] 用户 $testuser 存在于系统中。"
        # 同时显示家目录下以.b开头的隐藏文件
        ls -a /home/$testuser/.b*
else
        echo "[失败] 用户 $testuser 在系统中不存在。"
fi

运行脚本:

[root@host1 ~]# bash test.sh
[失败] 用户 ubuntu 在系统中不存在。

if-then-elif-else 多分支语句

if condition1
then
command1 
...
elif condition2
then
command1
...
else
command1
...
fi

作业1:先在/home/目录下创建名为ubuntu的目录,然后参考修改上一个脚本添加elif分支检测当用户ubuntu不存在,但是存在同名的ubuntu目录时在改目录中创建一个空文件tmp,提交执行结果。

条件判断

  • test 命令

    如果test命令中列出的条件成立,test命令就会退出并返回退出状态码0。这样if-then语句就与其他编程语言中的if-then语句以类似的方式工作了。如果条件不成立,test命令就会退出并返回非零的退出状态码,这使得if-then语句不会再被执行。

  • test命令格式

    if test condition
    then
     commands
    fi
  • bash shell提供了另一种条件测试方法,无需在if-then语句中声明test命令。

    if [ condition ]
    then
     commands
    fi

    创建脚本test.sh、编辑以下内容:

    #!/bin/bash
    
    testuser=centos
    
    # 当变量 testuser 不为空时执行 then 语句的内容
    if [ $testuser ]
    then
            echo "变量 testuser 的值当前为: $testuser"
    fi

    运行脚本:

    [root@host1 ~]# bash test.sh
    变量 testuser 的值当前为: centos

方括号定义了测试条件。注意,第一个方括号之后和第二个方括号之前必须加上一个空格,否则就会报错。

一共可以总结为三类条件:

  1. 文件比较

    这些测试条件使你能够在shell脚本中检查文件系统中的文件。它们经常出现在需要进行文件访问的脚本中,文件比较的操作符如下:

    1711544451619.png

    创建脚本test.sh、编辑以下内容:

    #!/bin/bash
    
    dir=/home/centos
    
    # 根据 -d 判断 dir 是否存在且是一个目录
    if [ -d $dir ]
    then
            echo "[状态] 目录 $dir 确实存在。"
            cd $dir
            ls
    fi

    运行脚本:

    [root@host1 ~]# bash test.sh
    [状态] 目录 /home/centos 确实存在。
    log.230616  test.sh
  2. 字符串比较

    1711544405818.png

    创建脚本test.sh、编辑以下内容:

    #!/bin/bash
    
    testuser=centos
    
    # 通过比较运算符等号 = 比较两个字符串,等式成立则表达式结果为真
    if [ $USER = $testuser ]
    then
            echo "[你好] 欢迎回来,$testuser!"
    fi

    运行脚本:

    [root@host1 ~]# bash test.sh
    [你好] 欢迎回来,centos!
    • 大于号和小于号必须转义,否则 shell 会把它们当作重定向符号,把字符串值当作文件名

    创建脚本 test.sh、编辑以下内容:

    #!/bin/bash
    
    var1=temp
    var2=tmp
    
    # 在条件比较时直接使用大于号 > 不能表示大于的含义,需要使用 \> 来表示“大于”
    if [ $var1 \> $var2 ]
    then
            echo "[结果] 字符串 $var1 大于 $var2"
    else
            echo "[结果] 字符串 $var1 不大于 $var2"
    fi

    运行脚本:

    [root@host1 ~]# bash test.sh
  3. 数值比较

    数值条件测试可以用在数字和变量上。

    1711544488016.png

复合条件测试

  • &&和|| 用法

    [ condition1 ] && [ condition2 ]
    [ condition1 ] || [ condition2 ]
    • 第一种布尔运算使用AND布尔运算符来组合两个条件。要让then部分的命令执行,两个条件都必须满足。
    • 第二种布尔运算使用OR布尔运算符来组合两个条件。如果任意条件为TRUE,then部分的命令就会执行。

作业2:参考以上字符串比较、复合条件测试的内容,检查当前系统是否存在名为centos的用户同时/home目录下是否存在名为centos的目录(文件比较),如果都成立则在该目录下创建一个空文件,运行脚本查看结果。

case命令

在shell编程中,case语句是一种多分支条件语句,用于测试变量或表达式是否与某些模式匹配,并执行相应的命令。

case语句通常用于替代if-then-else语句,特别是在需要测试一个变量或表达式是否匹配多个模式的情况下。case语句的语法结构如下:

case expression in
  pattern1)
    command1
    ;;
  pattern2)
    command2
    ;;
  pattern3)
    command3
    ;;
  *)
    default_command
    ;;
esac

其中,expression是要测试的变量或表达式,pattern1、pattern2、pattern3等是匹配模式,command1、command2、command3等是匹配模式成立时要执行的命令,;;表示命令结束,*)表示如果所有模式都不匹配时要执行的默认命令。

创建脚本test.sh、编辑以下内容:

#!/bin/bash

fruit="apple"

case $fruit in
        apple)
                echo "[匹配] 这是一个苹果。"
                ;;
        banana)
                echo "[匹配] 这是一个香蕉。"
                ;;
        # * 用来匹配之前所有模式都匹配不到的情况
        *)
                echo "[提示] 既不是苹果也不是香蕉。"
                ;;
esac

运行脚本:

[root@host1 ~]# bash test.sh
[匹配] 这是一个苹果。

作业3:编写程序实现以下要求

  1. 使用 read要求用户输入一个数字。
  2. 使用 if判断该数字是否在0-9之间,如果不满足则停止脚本。
  3. 然后使用 case 语句输出对应数字0-2的英文,对于其他数字输出一个提示“该数字在4-9之间”。