Linux Shell 编程之条件语句详解
Linux Shell编程之条件语句
Shell脚本是Linux系统自动化运维、批量处理任务的核心工具,而条件语句是让Shell脚本拥有“判断能力”的关键,能根据不同条件执行不同操作,让脚本从简单的命令拼接升级为具备逻辑思维的程序。本文将从基础的条件测试操作入手,详细讲解if条件语句和case分支语句的使用,并补充实用知识点,内容简易易懂、侧重实操。
一、基础条件测试操作
Shell通过返回状态值判断命令执行结果,返回0表示成功/条件成立,非0表示失败/条件不成立。条件测试是实现判断的基础,专门用于检测文件状态、数值大小、字符串匹配等情况,核心有两种写法,方括号写法更常用:
test 条件表达式[ 条件表达式 ]
注意:方括号与条件表达式之间必须有至少一个空格,这是Shell语法的硬性要求,遗漏会直接报错。
根据测试对象不同,条件测试分为文件测试、整数值比较、字符串比较和逻辑测试四类,以下是最常用的测试选项及实操示例。
1. 文件测试:判断文件/目录的状态
针对文件或目录的路径,检测其是否存在、类型、权限等,操作选项放在测试对象前,常用选项如下:
选项 | 作用 |
|---|---|
-d | 测试是否为目录(Directory) |
-e | 测试文件/目录是否存在(Exist) |
-f | 测试是否为普通文件(File) |
-r | 测试当前用户是否有读取权限(Read) |
-w | 测试当前用户是否有写入权限(Write) |
-x | 测试当前用户是否有执行权限(Execute) |
示例:测试/tmp/test是否为目录 [ -d /tmp/test ] echo $? (查看前一条命令的返回值,返回0为成立 非0为不成立)示例:测试/tmp/test是否为目录,存在则输出“存在” [ -d /tmp/test ] && echo "存在" (无输出表示该目录不存在,输出则表示存在)&&为逻辑与,仅当前面命令执行成功(条件成立)时,才执行后面的命令。
2. 整数值比较:判断两个整数的大小
仅适用于整数比较,不能用于小数/字符串,操作选项放在两个整数之间,常用选项如下:
选项 | 作用 |
|---|---|
-eq | 两数相等(Equal) |
-ne | 两数不相等(Not Equal) |
-gt | 第一个数大于第二个数(Greater Than) |
-lt | 第一个数小于第二个数(Lesser Than) |
-le | 第一个数小于等于第二个数 |
-ge | 第一个数大于等于第二个数 |
示例:判断当前登录用户数是否超过3,超过则提示“用户过多” num=$(who | wc -l) # 提取登录用户数 [ $num -gt 3 ] && echo "用户过多"3. 字符串比较:判断字符串是否匹配/为空
用于检测字符串是否相同、是否为空,常用于判断用户输入、系统环境变量,常用选项如下:
选项 | 作用 |
|---|---|
= | 两个字符串完全相同(注意是单等号) |
!= | 两个字符串不相同,其中“!”符号表示取反 |
-z | 测试字符串是否为空(长度为0) |
-n | 测试字符串是否非空(长度不为0) |
示例1:判断系统语言是否为中文,非中文则提示 [ $LANG != "zh_CN.UTF-8" ] && echo "当前非中文环境" 示例2:判断用户输入是否为空,为空则提示 read -p "请输入内容:" input [ -z $input ] && echo "输入内容不能为空"4. 逻辑测试:判断多个条件的关系
用于组合多个测试条件,判断其“与/或/非”关系,常用操作如下(推荐符号写法,更直观):
操作符 | 作用 | 等价写法(test命令用) |
|---|---|---|
&& | 逻辑与:多个条件同时成立才成立 | -a |
|| | 逻辑或:多个条件一个成立就成立 | -o |
! | 逻辑非:取反,条件不成立时结果才成立 | ! |
示例:判断整数num是否在10~20之间 num=15 [ $num -ge 10 ] && [ $num -le 20 ] && echo "在10~20之间" 补充:逻辑非的使用,测试/tmp/test是否不是目录 [ ! -d /tmp/test ] && echo "不是目录或不存在"补充知识点1:条件测试的简化输出
除了&&,还可搭配||(逻辑或)实现“条件成立输出A,不成立输出B”,无需额外语句,极简实用: # 测试/tmp/test是否存在,存在输出“存在”,否则输出“不存在” [ -e /tmp/test ] && echo "存在" || echo "不存在"二、if条件语句:按条件执行不同命令序列
条件测试仅能实现简单的判断输出,当需要根据条件执行多条命令时,需使用if条件语句。根据逻辑复杂度,分为单分支、双分支、多分支三种结构,核心特点是层次清晰、适合多条件嵌套。
1. 单分支if语句:条件成立才执行
适用场景:仅需要在“条件成立”时执行命令,条件不成立则无操作。
语法格式:
if 条件测试操作
then
命令序列 # 条件成立时执行,可写多条命令
fi # 结束if判断,不可省略
示例:检测备份目录/data/backup是否存在,不存在则创建 #!/bin/bash BACKUP_DIR="/data/backup" if [ ! -d $BACKUP_DIR ] then mkdir -p $BACKUP_DIR echo "备份目录创建成功:$BACKUP_DIR" fi2. 双分支if语句:条件成立/不成立分别执行
适用场景:需要对“条件成立”和“条件不成立”两种情况分别执行不同命令序列,是最常用的结构。
语法格式:
if 条件测试操作
then
命令序列1 # 条件成立执行
else
命令序列2 # 条件不成立执行
fi
示例:检测目标主机是否连通,连通则提示在线,否则提示离线 #!/bin/bash IP=$1 # 接收位置参数,指定目标IP ping -c 2 -i 0.5 -W 2 $IP &>/dev/null # 发送2个包,超时2秒,屏蔽输出 if [ $? -eq 0 ] # $?获取上一条命令返回值,0表示ping通 then echo "主机$IP 在线" else echo "主机$IP 离线" fi 执行效果: bash ping_host.sh 192.168.1.100 # 检测192.168.1.1003. 多分支if语句:多个条件依次判断
适用场景:存在多个互斥条件,需要依次判断,满足某个条件则执行对应命令,所有条件都不满足则执行默认命令。
语法格式:
if 条件测试操作1
then
命令序列1 # 条件1成立执行
elif 条件测试操作2
then
命令序列2 # 条件2成立执行 # 可添加多个elif条件
else
命令序列n # 所有条件都不成立执行
fi
示例:根据用户输入的分数,判断成绩等级(85+优秀、60~84及格、60以下不及格,可以检测输入的是不是数字如不是会提升输入数字而不是符号或其他,数字不会超过100) vim aaa.sh #!/bin/bash # 循环接收输入,直到输入合法 while true; do read -p "输入您的分数(0-100):" GRADE # 第一步:正则校验是否为纯数字(仅允许0-9的数字,无其他字符) if ! [[ $GRADE =~ ^[0-9]+$ ]]; then echo "错误:请输入纯数字,请勿输入字母、符号或空格!" continue fi # 第二步:校验数字是否在0-100范围内 if [ $GRADE -lt 0 ] || [ $GRADE -gt 100 ]; then echo "错误:分数范围必须在0-100之间,请重新输入!" continue fi # 输入合法,退出循环 break done # 原有分数等级判断逻辑 if [ $GRADE -ge 85 ] && [ $GRADE -le 100 ]; then echo "$GRADE 分,优秀!" elif [ $GRADE -ge 60 ] && [ $GRADE -le 84 ]; then echo "$GRADE 分,合格!" else echo "$GRADE 分,不及格!" fi 执行: bash aaa.sh (然后输入自己的数字)补充知识点2:if语句的条件拓展
if后的条件测试操作不仅可以是[ 表达式 ],还可以是任意Linux命令,Shell会根据命令的返回值判断:返回0则条件成立,非0则不成立。
示例:直接用ping命令作为if条件,简化主机连通性检测
if ping -c 2 192.168.1.100 &>/dev/null then echo "主机在线" else echo "主机离线" fi
三、case分支语句:匹配变量的多个取值
case语句与多分支if语句功能类似,专门适用于“一个变量有多个固定取值,每个取值对应不同操作” 的场景,相比多分支if语句,case语句语法更简洁、可读性更高,无需多次写条件测试,仅需匹配变量取值。
1. case语句的基本语法
核心特点:按顺序匹配变量的取值,匹配成功则执行对应命令序列,匹配后直接退出(无需判断后续条件),无匹配项则执行默认操作。
case 变量值 in
模式1)
命令序列1
;; # 结束当前模式,不可省略,相当于“break”
模式2)
命令序列2
;; # 可添加多个模式
*) # 通配符,匹配所有未定义的模式,即默认模式 默认命令序列
esac # 结束case判断,不可省略
2. 模式匹配规则(实用拓展)
case的模式支持通配符和范围匹配,让取值匹配更灵活,常用规则:
[a-z]:匹配小写字母a到z的任意一个;[0-9]:匹配数字0到9的任意一个;A|B:匹配A或B,如start|begin;*:通配符,匹配任意字符(即默认模式*);?:匹配单个任意字符。
3. case语句实操示例
示例1:判断用户输入的字符类型
提示用户输入一个字符,判断其是字母、数字还是其他字符: #!/bin/bash read -p "请输入一个字符:" key case $key in [a-z]|[A-Z]) # 匹配任意字母 echo "您输入的是【字母】" ;; [0-9]) # 匹配任意数字 echo "您输入的是【数字】" ;; *) # 匹配其他所有字符 echo "您输入的是【特殊字符/空格/功能键】" esac示例2:编写简易服务控制脚本
模拟Linux系统服务的start/stop/restart/status控制,实现对sleep进程的启停管理(sleep仅作测试,可替换为实际服务如nginx): #!/bin/bash # 服务控制脚本:./service.sh start/stop/restart/status case $1 in start) echo -n "正在启动服务..." sleep 3600 &>/dev/null & # 后台启动sleep进程 echo "启动成功" ;; stop) echo -n "正在停止服务..." pkill sleep &>/dev/null # 终止sleep进程 echo "停止成功" ;; restart) $0 stop # $0表示当前脚本名,调用自身的stop操作 $0 start # 调用自身的start操作 echo "重启成功" ;; status) if pgrep sleep &>/dev/null; then echo "服务【运行中】" else echo "服务【已停止】" fi ;; *) echo "用法:$0 {start|stop|restart|status}" # 提示正确用法 esac 执行效果: bash service.sh start # 启动服务 bash service.sh status # 查看状态 bash service.sh stop # 停止服务补充知识点3:if与case的适用场景对比
if和case都能实现多条件判断,核心区别在于判断依据,实际使用中按以下原则选择,让脚本更简洁:
- 用if的场景:判断多个不同的条件(如数值范围、多个文件状态、混合条件),或条件之间有嵌套关系;
- 用case的场景:判断一个变量的多个固定取值(如服务的start/stop、字符类型、菜单选择),取值为离散的固定值。
四、核心语法注意事项(避坑重点)
- 方括号
[ ]与条件表达式之间必须有空格,如[ $num -gt 10 ],不可写为[$num -gt 10]; - 变量取值建议用双引号包裹,避免因空格、特殊字符导致报错,如
[ -z "$input" ]; - case语句中,每个模式必须以
)结束,命令序列后必须加;;,否则脚本执行异常; - 整数值比较不能用
>/<,Shell中</>是重定向符号,会导致语法错误,必须用-gt/-lt等; - 字符串比较的
=前后建议加空格,避免与变量赋值混淆(赋值是变量=值,无空格)。
五、本章小结
- 条件测试是Shell判断的基础,分为文件、整数值、字符串、逻辑四类,
[ 表达式 ]是最常用写法; - if条件语句分单/双/多分支,适合多条件、多场景的逻辑判断,支持命令作为条件;
- case分支语句适合单变量的多固定取值匹配,语法简洁、执行效率高,支持通配符模式匹配;
- 实际脚本编写中,根据判断依据选择if或case,同时注意Shell的语法细节,避免空格、符号等低级错误。
掌握条件语句后,Shell脚本将具备基本的逻辑处理能力,后续可结合循环语句实现更复杂的自动化任务(如批量检测主机、批量备份文件、自动化部署服务等),是Linux自动化运维的必备基础。