Shell if else语句用法详解(附带实例)
程序语言的流程控制主要包含以下三大类:
请大家注意,shell 语句是顺序执行的,而且可以直接使用 Linux 的命令,因此更加利于系统管理和维护。
if 语句能够在判断成立或不成立之后执行不同的操作。我们可以在脚本中定义,当某些条件成立时执行对应的 A 程序,当条件未成立时执行 B 程序。我们还可以在脚本中给出多种条件,只要满足了其中的某个条件,就执行相应的某些程序。
单分支 if 条件语句的执行过程如下图所示:

图 1 单分支if条件语句的执行过程
单分支 if 条件语句的语法如下:
单分支 if 条件语句非常简单,但是千万不要小看它,这是流程控制语句最基本的语法。而且在实现 Linux 管理时,我们的管理脚本一般都不复杂,使用单分支 if 条件语句的概率还是很高的。
例如,~/.bashrc 文件中就存在单分支 if 条件语句:
接下来使用单分支 if 条件语句编辑一个 shell 脚本,例如,我想通过脚本判断根分区的使用率是否超过 80%,如果超过 80% 就向管理员报警,请注意,那么脚本可以这样写:
这条命令的执行结果如下:
提取出根分区的使用率后,判断这个数字是否大于等于 80,如果大于等于 80 就报警。至于报警信息,我们可以通过脚本直接输出到屏幕上。在实际工作中,因为服务器屏幕并不是24小时都有人值守的,所以也可以给管理员发送邮件,用于报警。
在脚本写好之后,就可以利用系统定时任务,让这个脚本每天或每几天执行一次,实现自动检测硬盘剩余空间。后续系统管理的脚本,如果需要重复执行,那么也可以使用系统定时任务来实现。
与单分支 if 条件语句相比,双分支 if 条件语句同样只有一个条件判断式。不同于单分支 if 条件语句,在执行双分支 if 条件语句之后,无论条件判断式成立或不成立,都有对应的执行程序,如下图所示。

图 2 双分支if条件语句的执行过程
语法如下:
例如,使用双分支 if 条件语句来进行目录判断:
接下来,使用双分支 if 条件语句判断变量 dir 的值是否为目录。假设判断成立,就执行 then 之后的程序,也就是 echo“yes”。假设判断不成立,就执行 else 之后的程序,也就是echo“no”。
再例如,在工作中,服务器上的服务可能会宕机。如果对服务器的监控不力,就会造成服务器上的服务宕机而管理员却不知道的情况。这时可以编写一个脚本来监听本机的服务,如果服务停止或宕机,就可以自动重启这些服务。我们拿 Apache 服务来举例:
因此,我们使用 nmap 端口扫描命令,如果系统中默认没有 nmap 端口,那么可以通过 dnf 安装,包名为 nmap。nmap 命令的格式如下:
这条命令的执行结果如下:
了解了 nmap 命令的用法后,我们在脚本中使用的命令就是为了截取 HTTP 的状态,只要状态是“open”就证明 Apache 服务启动正常,否则证明 Apache 服务启动错误。来看看脚本中命令的执行结果:
多分支 if 条件语句的执行过程如下图所示:

图 3 多分支if条件语句的执行过程
语法如下:
例如,使用多分支 if 条件语句来判断用户输入的是一个文件还是一个目录,具体如下:
在多分支 if 条件语句中:
注意,在编辑多分支 if 条件语句时,我们使用的多个条件判断式会按照编辑顺序从上到下进行判断,哪个判断成立就执行相对应的 then 中的程序,程序执行后就结束整体 if 判断。因此,在上面的多分支if条件语句中,假设我们把文件是否存在的判断写在普通文件和目录判断之前,就永远不可能执行普通文件和目录的判断,因为在判断文件存在成立后就会执行相应程序,程序执行后就会退出 if 判断,并不会进行后续条件判断。
再例如,在之前的位置参数变量和 read 语句中,我们曾经多次编辑过四则运算的计算器,现在把 if 判断加入计算,就可以用于判断 read 语句的值是否为空,还可以判断要用来计算的运算符号。
通过第三层判断运算符我们可以看到,对于 if 条件判断式来说,其可以进行类型判断,如文件类型的判断、文件权限的判断及数字大小的判断,也可以对某些具体的指定字符串进行判断。
执行一下这个脚本:
- 条件判断控制(if、case)。
- 循环控制(for、while、until)。
- 特殊流程控制语句(exit、break、continue)。
请大家注意,shell 语句是顺序执行的,而且可以直接使用 Linux 的命令,因此更加利于系统管理和维护。
if 语句能够在判断成立或不成立之后执行不同的操作。我们可以在脚本中定义,当某些条件成立时执行对应的 A 程序,当条件未成立时执行 B 程序。我们还可以在脚本中给出多种条件,只要满足了其中的某个条件,就执行相应的某些程序。
Shell if单分支条件语句
单分支 if 条件语句的格式相对简单,只有一个判断条件,只有判断条件成立时才执行相应程序,否则结束判断。单分支 if 条件语句的执行过程如下图所示:

图 1 单分支if条件语句的执行过程
单分支 if 条件语句的语法如下:
if [ 条件判断式 ];then 程序 fi在使用单分支 if 条件语句时需要注意以下几点:
- 除 [条件判断式] 判断外,还可以根据需求选择 [[条件判断式]] 进行判断。
- then 后面为符合条件之后执行的程序,可以放在 [] 之后,用“;”分隔;也可以换行写入,这样就不需要写“;”了,例如,单分支 if 条件语句还可以这样写:
if [ 条件判断式 ] then 程序 fi
单分支 if 条件语句非常简单,但是千万不要小看它,这是流程控制语句最基本的语法。而且在实现 Linux 管理时,我们的管理脚本一般都不复杂,使用单分支 if 条件语句的概率还是很高的。
例如,~/.bashrc 文件中就存在单分支 if 条件语句:
[root@localhost ~]# cat ~/.bashrc ...省略部分文件内容... if [ -f /etc/bashrc ]; then . /etc/bashrc fi ...省略部分文件内容...在 .bashrc 文件中使用单分支 if 条件语句判断是否存在 /etc/bashrc 文件,如果 /etc/bashrc 文件存在,就使用“.”让/etc/bashrc文件在当前 shell 中生效。
接下来使用单分支 if 条件语句编辑一个 shell 脚本,例如,我想通过脚本判断根分区的使用率是否超过 80%,如果超过 80% 就向管理员报警,请注意,那么脚本可以这样写:
[root@localhost ~]# df -h #查看服务器的分区状况 文件系统 容量 已用 可用 已用%% 挂载点 /dev/sda3 20G 1.8G 17G 10% / tmpfs 306M 0 306M 0% /dev/shm /dev/sda1 194M 26M 158M 15% /boot /dev/sr0 3.5G 3.5G 0 100% /mnt/cdrom [root@localhost ~]# vim /root/if1.sh #!/bin/bash #统计根分区的使用率 rate=$(df -h | grep "/dev/sda3" | awk '{print $5}' | cut -d "%" -f1) #把根分区使用率作为变量赋予变量 rate if [ $rate -ge 80 ] #判断变量 rate 的值,如果大于等于 80,就执行 then 程序 then echo "Warning!/dev/sda3 is full!!!" #打印警告信息。在实际工作中,也可以向管理员发送邮件 fi其实,这个脚本最重要的地方是“rate=$(df-h|grep"/dev/sda3"|awk'{print$5}'|cut-d"%"-f1)”,我们来分析一下这条命令:
- 首先使用“df-h”列出系统中的分区情况;
- 其次使用“grep”命令提取出根分区行;
- 再次使用“awk”命令列出第五列,也就是根分区使用率这一列(不过使用率是10%,不好比较,还要提取 10 这个数字);
- 最后使用 cut 命令(cut 命令比 awk 命令简单),以“%”作为分隔符,提取出第一列。
这条命令的执行结果如下:
[root@localhost ~]# df -h | grep "/dev/sda3" | awk '{print $5}' | cut -d "%" -f1 10
提取出根分区的使用率后,判断这个数字是否大于等于 80,如果大于等于 80 就报警。至于报警信息,我们可以通过脚本直接输出到屏幕上。在实际工作中,因为服务器屏幕并不是24小时都有人值守的,所以也可以给管理员发送邮件,用于报警。
在脚本写好之后,就可以利用系统定时任务,让这个脚本每天或每几天执行一次,实现自动检测硬盘剩余空间。后续系统管理的脚本,如果需要重复执行,那么也可以使用系统定时任务来实现。
Shell双分支if条件语句
在双分支 if 条件语句中,当条件判断式成立时,就执行某个程序;当条件判断式不成立时,就执行另一个程序。与单分支 if 条件语句相比,双分支 if 条件语句同样只有一个条件判断式。不同于单分支 if 条件语句,在执行双分支 if 条件语句之后,无论条件判断式成立或不成立,都有对应的执行程序,如下图所示。

图 2 双分支if条件语句的执行过程
语法如下:
if [ 条件判断式 ] then 当条件判断式成立时,执行的程序 else 当条件判断式不成立时,执行的另一个程序 fi
例如,使用双分支 if 条件语句来进行目录判断:
#!/bin/bash read -t 30 -p "Please input a directory:" dir #通过 read 语句接收键盘的输入,并存入变量 dir if [ -d $dir ] #测试 $dir 中的内容是否是一个目录 then echo "yes" #如果是一个目录,就输出 yes else echo "no" #如果不是一个目录,就输出 no fi解释一下脚本思路,首先通过 read 语句接收键盘输入。read 输出提示“Please input a directory:”,将键盘输入的字符串赋值给变量 dir。
接下来,使用双分支 if 条件语句判断变量 dir 的值是否为目录。假设判断成立,就执行 then 之后的程序,也就是 echo“yes”。假设判断不成立,就执行 else 之后的程序,也就是echo“no”。
再例如,在工作中,服务器上的服务可能会宕机。如果对服务器的监控不力,就会造成服务器上的服务宕机而管理员却不知道的情况。这时可以编写一个脚本来监听本机的服务,如果服务停止或宕机,就可以自动重启这些服务。我们拿 Apache 服务来举例:
[root@localhost ~]# vim /root/autostart.sh #!/bin/bash #判断 Apache 服务是否运行,如果没有运行就启动服务并记录启动服务时间,如果服务正常运行就只进行记录 port=$(nmap -sT 192.168.4.210 | grep tcp | grep http | awk '{print $2}') #使用 nmap 命令扫描服务器,并截取 Apache 服务的状态,赋予变量 port if [ "$port" == "open" ] #如果变量 port 的值是 "open" then echo "$(date) httpd is ok!" >> /tmp/autostart-acc.log #就证明 Apache 服务正常运行,在正确日志中写入一句话即可 else systemctl start httpd.service &>/dev/null #否则证明 Apache 服务没有启动,启动 Apache 服务 echo "$(date) restart httpd !!!" >> /tmp/autostart-err.log #并在错误日志中记录自动启动 Apache 服务的时间 fi解释一下脚本思路,在这个例子中,关键点是如何判断 Apache 服务是否启动了。如果使用 netstat-tlun 命令或 ps aux 命令,就只能判断本机的 Apache 服务是否启动,而不能判断远程服务器是否启动了 Apache 服务。而如果使用 telnet 命令,那么虽然可以探测远程服务器的80端口是否启动,但是要想退出探测界面,还需要执行人机交互,非常麻烦。
因此,我们使用 nmap 端口扫描命令,如果系统中默认没有 nmap 端口,那么可以通过 dnf 安装,包名为 nmap。nmap 命令的格式如下:
[root@localhost ~]# nmap -sT 域名或 IP选项:
- -sS:扫描;
- -T:扫描所有开启的 TCP 端口。
这条命令的执行结果如下:
[root@localhost ~]# nmap -sT 192.168.4.210 #可以看到,这台服务器开启了如下服务 Starting Nmap 7.92 ( http://nmap.org ) at 2024-03-26 16:12 CST Nmap scan report for 192.168.4.210 Host is up (0.0010s latency). Not shown: 994 closed ports PORT STATE SERVICE 22/tcp open ssh 80/tcp open http <--Apache 服务的状态是 open 111/tcp open rpcbind 139/tcp open netbios-ssn 445/tcp open microsoft-ds 3306/tcp open mysql Nmap done: 1 IP address (1 host up) scanned in 0.49 seconds
了解了 nmap 命令的用法后,我们在脚本中使用的命令就是为了截取 HTTP 的状态,只要状态是“open”就证明 Apache 服务启动正常,否则证明 Apache 服务启动错误。来看看脚本中命令的执行结果:
[root@localhost ~]# nmap -sT 192.168.4.210 | grep tcp | grep http | awk '{print $2}' ###首先指定计算机,先提取包含 tcp 的行,再提取包含 httpd 的行,截取第二列 open #把截取的值赋予变量 port
Shell多分支if条件语句
在多分支 if 条件语句中,可以使用多个条件判断式,多个条件判断式会逐一进行判断。若判断成立则执行对应程序,对应程序执行完成后结束当前整体 if 判断;若判断不成立则继续逐个使用执行条件判断式进行判断,如果所有条件判断式均未判断成立,就执行 else 后的语句,else 语句执行后,整体 if 判断结束。多分支 if 条件语句的执行过程如下图所示:

图 3 多分支if条件语句的执行过程
语法如下:
if[ 条件判断式 1 ] then 程序 1 elif[ 条件判断式 2 ] then 程序 2 ...省略更多条件... else 上述所有条件均未成立执行此程序 fi
例如,使用多分支 if 条件语句来判断用户输入的是一个文件还是一个目录,具体如下:
[root@localhost ~]# cat /root/if-elif.sh #!/bin/bash read -p "Please input a filename:" file #接收键盘输入,赋值给变量 file if[ -z "$file" ] #判断 file 变量值是否为空 then echo "error,Please input a file name!" #如果 file 变量值为空就输出错误提示信息 elif[ -f "$file" ] #判断 file 变量值是否为普通文件 then echo "$file is a regular file!" #如果 file 变量值为普通文件就输出提示 elif[ -d "$file" ] #判断 file 变量值是否为目录 then echo "$file is a directory!" #如果 file 变量值为目录就输出提示 elif[ -e "$file" ] #判断 file 变量值是否存在 then echo "$file not regular file or directory!" #file 变量值为存在的文件,说明文件存在,但文件类型既不是普通文件也不是目录文件 else echo "$file file does not exist!" #如果以上所有判断不成立,就执行 else 后代码 fi解释一下脚本思路,在脚本执行后,再通过执行 read 语句输出提示信息,并将用户键盘输入的字符串赋值给变量file。
在多分支 if 条件语句中:
- 首先,进行多分支 if 判断。先判断 $file 取值是否为空,如果输入为空就输出 error 错误提示信息,结束 if 判断;如果输入不为空,那么判断不成立,继续执行下一个条件判断式;
- 其次,判断 $file 取值是不是普通文件。如果判断成立,就输出 regular file 提示,结束 if 判断;如果输入的字符串不是普通文件,就继续执行下一个条件判断式;
- 再次,判断 $file 取值是不是目录。如果判断成立,就输出 directory 提示,结束 if 判断;如果输入的字符串不是目录,就继续执行下一个条件判断式。
- 经过上面三个条件判断式,我们已经可以确定 $file 是非空字符串,并且既不是普通文件也不是目录文件。然后,判断 $file 字符串是否存在,假设存在,就意味着 $file 的值是除普通文件和目录外的其他类型的文件。
- 最后,如果以上判断全部不成立,就执行 else 后的提示。
注意,在编辑多分支 if 条件语句时,我们使用的多个条件判断式会按照编辑顺序从上到下进行判断,哪个判断成立就执行相对应的 then 中的程序,程序执行后就结束整体 if 判断。因此,在上面的多分支if条件语句中,假设我们把文件是否存在的判断写在普通文件和目录判断之前,就永远不可能执行普通文件和目录的判断,因为在判断文件存在成立后就会执行相应程序,程序执行后就会退出 if 判断,并不会进行后续条件判断。
再例如,在之前的位置参数变量和 read 语句中,我们曾经多次编辑过四则运算的计算器,现在把 if 判断加入计算,就可以用于判断 read 语句的值是否为空,还可以判断要用来计算的运算符号。
[root@localhost ~]# vim /root/sum.sh #!/bin/bash #字符界面加减乘除计算器 read -t 30 -p "Please input num1:" num1 read -t 30 -p "Please input num2:" num2 #通过 read 语句接收要计算的数值,并赋予变量 num1 和 num2 read -t 30 -p "Please input a operator:" ope #通过 read 语句接收要计算的符号,并赋予变量 ope if [ -n "$num1" -a -n "$num2" -a -n "$ope" ] #第一层判断,用来保证变量 num1、num2 和 ope 中都有值 then test1=$(echo $num1 | sed 's/[0-9]//g') test2=$(echo $num2 | sed 's/[0-9]//g') #定义变量 test1 和 test2 的值为 $(命令) 的结果 #后续命令的作用是把变量 test1 的值替换为空。如果能替换为空,就证明变量 num1 的值为数字 #如果不能替换为空,就证明变量 num1 的值为非数字。我们使用这种方法判断得出变量 num1 的值为数字 #用同样的方法测试变量 test2 if [ -z "$test1" -a -z "$test2" ] #第二层判断,用来保证变量 num1 和 num2 的值为数字 #如果变量 test1 和 test2 的值为空,就证明变量 num1 和 num2 的值为数字 then #如果变量 test1 和 test2 的值为数字,就执行以下命令 if [ "$ope" == '+' ] #第三层判断,用来确认运算符 #测试变量 $ope 中是什么运算符 then sum=$( ( $num1 + $num2 )) #如果是加号,就执行加法运算 elif [ "$ope" == '-' ] then sum=$( ( $num1 - $num2 )) #如果是减号,就执行减法运算 elif [ "$ope" == '*' ] then sum=$( ( $num1 * $num2 )) elif [ "$ope" == '/' ] then sum=$( ( $num1 / $num2 )) else echo "Please enter a valid symbol" #如果运算符不匹配,就提示输入有效的符号 fi else #如果变量 test1 和 test2 的值不为数字 echo "Please enter a valid value" #就提示输入有效的数值 fi else #如果变量 num1、num2 和 ope 中没有内容这个脚本的逻辑比较复杂,出现了三层判断。因为我们很难控制用户到底输入了什么内容,所以必须加入必要的判断,以此保证程序正确运行:
- 第一层判断用来保证三个变量中都有值;
- 第二层判断用来保证变量 num1 和 num2 的值是数字;
- 第三层判断用来确认运算符。
通过第三层判断运算符我们可以看到,对于 if 条件判断式来说,其可以进行类型判断,如文件类型的判断、文件权限的判断及数字大小的判断,也可以对某些具体的指定字符串进行判断。
执行一下这个脚本:
[root@localhost ~]# ./root/sum.sh Please input num1: y Please input num2: u #如果没有输入数字 Please input a operator: + Please enter a valid value #就报错,请输入正确的数值 [root@localhost ~]# ./sh/sum.sh Please input num1: 6 Please input num2: 9 Please input a operator: k #如果运算符输入错误 Please enter a valid symbol #就报错,请输入有效的符号 [root@localhost ~]# ./sh/sum.sh Please input num1: 6 Please input num2: 9 Please input a operator: * 6 * 9 : 54 #如果输入都正确,脚本就可以正确地进行运算