课前拓展: 我们都知道布尔值(bool):条件成立输出 1,不成立输出 0。但在shell编程中绝大多数规则却相反,件成立返回 0,条件不成立返回 非 0(常见为 1)。
这里我们不去深究原因,但是要进行区分清楚这两种情况:
- 满足布尔特性,成立 = 1,不成立 = 0(是1非0)的:数学运算($(()) /bc比较运算)
- 不满足布尔特性(是0非1)的:条件判断:[ ]、test、[[ ]]、所有文件 / 字符串 / 权限测试表达式
总结:
算数比较:1 真 0 假
Shell 判断:0 真 1 假
一、条件测试:让 Shell 拥有"判断能力"
1.1 Shell 脚本智能化
条件测试是脚本实现自动化的核心,用于为命令执行提供判断依据,支持四类判断:
- 文件/目录的存在、权限、类型状态
- 整数大小比较
- 字符串匹配/空值判断
- 多条件逻辑组合
1.2 [ ] 条件测试基础
Shell 提供两种条件测试写法,[ ] 为最常用写法:
- 方式1:test 命令(几乎已经不再使用)
test 选项 参数
- 方式2:[ ] 写法(推荐)
[ 选项 参数 ]
✅ 强制规范 :
[ ]内侧左右必须各留至少一个空格,否则语法报错。
1.3字符串比较
单字符串判断(空/非空)
bash
[ 操作符 字符串 ]
-z:判断字符串为空 ,成立返回0,失败返回非 0! -z(注意!与-z之间的空格):判断字符串非空 ,等价于-n(不建议使用)
(-n虽然与!z等价,但是-n使用起来注意事项较多,更建议使用!z)
bash
[root@server ~]# [ -z abc ] #判断字符串abc是空的,失败/错误(注意:不加$代表只是普通的字符串而不是变量,字符串当然不是空的)
[root@server ~]# echo $? #查看返回值为非0
1
[root@server ~]# [ -n abc ] #判断字符串abc是非空的,成功/正确
[root@server ~]# echo $? #查看返回值为0
0
[root@server ~]# name=zhangsan #定义变量name,值为zhangsan
[root@server ~]# [ -z "$name" ] #判断变量$name的值是空的,失败/错误
[root@server ~]# echo $? #查看返回值为非0
1
双字符串比较:
bash
[ 字符串1 操作符 字符串2 ]
==:两个字符串相同!=:两个字符串不相同
bash
[root@server ~]# [ abc == haha ] #判断两个字符串相同,失败/错误
[root@server ~]# echo $? #查看返回值为非0
[root@server ~]# [ abc == abc ] #判断两个字符串相同,正确/成功
[root@server ~]# echo $? #查看返回值为0
[root@server ~]# name=lisi #定义变量name,值为lisi
[root@server ~]# [ lisi == $name ] #判断lisi和name变量值相同,正确/成功
[root@server ~]# echo $? #查看返回值为0
[root@server ~]# class=cloud #定义变量class,值为cloud
[root@server ~]# [ $class == $name ] #判断两个变量值相同,正确/成功
[root@server ~]# echo $? #查看返回值为0
1
1.4整数比较
整数比较操作符
bash
[ 整数值1 操作符 整数值2 ]

基础示例
bash
[root@server ~]# [ 3 -eq 3 ]
[root@server ~]# echo $?
0
[root@server ~]# [ 3 -eq 8 ]
[root@server ~]# echo $?
1
[root@server ~]# [ 5 -lt 20 ]
[root@server ~]# echo $?
0
[root@server ~]# [ 5 -lt 2 ]
[root@server ~]# echo $?
1
建议这样简化操作步骤:
[ a 操作符 b ] && echo $?
这里仅仅是基础演示写的较为繁琐一些
变量与命令结果比较
- 整数比较支持变量比较、也支持对表达式的运行结果比较
bash
[root@server ~]# age=18 #定义变量age,值为18
[root@server ~]# [ $age -eq 30 ] #判断age变量的值等于30,失败/错误
[root@server ~]# echo $? #返回值结果为非0
[root@server ~]# ps aux | wc -l #统计系统进程数量
[root@server ~]# [ $(ps aux | wc -l) -ge 100 ] #判断系统进程数量大于100
[root@server ~]# echo $? #查看返回值
1.5文件状态测试
bash
[ 操作符 文件/目录 ]
(重点是前三个选项)

- 注意:-d,-f也可以确认文件是否存在
-
-f 文件名 \] **文件存在 且 是普通文件**
因此-f/-d可以直接用来判断文件/目录是否存在
-
bash
[root@server ~]# [ -e /etc ] #判断/etc存在
[root@server ~]# echo $? #返回0
[root@server ~]# [ -e /etc/hosts ] #判断/etc/hosts存在
[root@server ~]# echo $? #返回0
[root@server ~]# [ -f /etc ] #判断/etc存在且是文件
[root@server ~]# echo $? #返回非0
[root@server ~]# [ -f /etc/hosts ] #判断/etc/hosts存在且是文件
[root@server ~]# echo $? #返回0
[root@server ~]# [ -d /etc ] #判断/etc存在且是目录
[root@server ~]# echo $? #返回0
[root@server ~]# [ -d /etc/hosts ] #判断/etc/hosts存在且是目录
[root@server~]# echo $? #返回非0
注意:权限判断中判断的是当前用户相对的权限
1.6多条件组合(&& / || / ;)
- 主要用法
-
条件1 \] 操作符 \[ 条件2
- 命令1 操作符 命令2
-
逻辑符含义

;:前命令执行完,继续执行后命令(不管前一条成功还是失败,无条件执行下一条)&&:逻辑与,都成立才为真。前一条执行成功,才执行后一条;前一条失败,直接终止不往后跑。||:逻辑或,一个成立即为真。前一条失败了,才执行后一条;前一条如果成功,就不执行后面。
常用示例
- 验证逻辑与&&和逻辑或||
bash
[root@server ~]# [ $USER == root ] && [ $UID -eq 0 ] #判断当前用户为root且UD为0,正确
[root@server ~]# echo $? #查看返回值为0
[root@server ~]# [ $HOME == /home/root ] || [ $USER == root ] #判断及目录为/home/root或当前用户为root
[root@server ~]# echo $? #查看返回值为0
- 使用控制符组合多个命令
bash
[root@server ~]# head -1 /etc/shells ; hostname #执行完命令1,再执行命令2
[root@server ~]# [ a == a ] && echo Y || echo N
Y
[root@server ~]# [ a == b ] && echo Y || echo N
N
[root@server ~]# [ 3 -eq 3 ] && echo Y || echo N
Y
[root@server ~]# [ 2 -lt 3 ] && echo Y || echo N
Y
[root@server ~]# [ -d /opt/testdir ] || mkdir /opt/testdir #判断若目录不存在,则创建目录
二、if 判断语句(单/双/多分支)
2.1 单分支 if
条件成立(返回值为0)则执行后续命令序列,不成立不执行。
bash
if 条件测试;then
命令序列
...
fi
也会遇见这种格式:
bash
if 条件测试
then 命令序列
...
fi
作用一致,只是不加分号之后then必须换行
案例:目录不存在则创建
bash
#!/bin/bash
dir=/haha
if [ ! -d $dir ];then
mkdir $dir
fi
案例:判断是否为 root 用户
bash
#!/bin/bash
if [ $UID -eq 0 ];then
echo "当前登录系统用户为 root"
fi
2.2 双分支 if
如果条件成立执行序列1,否则执行序列2,匹配即停止。
bash
if 条件测试;then
命令序列1
else
命令序列2
fi
案例:ping 检测主机连通性
- 用户执行脚本时通过位置变量传入参数,判断目标主机是否可以通信
- ping命令常用选项:-c 指定ping的次数、-i指定速度、-W指定等待时间(秒)
bash
#!/bin/bash
#此处$1是位置变量。是用户传递的参数(IP地址)
ping -c 4 -i 0.2 -W 1 $1 &> /dev/null
if [ $? -eq 0 ];then
echo "$1 通了"
else
echo "$1 不通"
fi
ping -c指定次数,-i指定时间间隔,-w指定超时时间
这里:命令 &> /dev/null,使用 $?输出的结果只看前面那条业务命令的退出码
2.3 多分支 if
多条件匹配,依旧是匹配即停止。
bash
if 条件1;then
命令1
elif 条件2;then
命令2
else
默认命令
fi
注意:中间的条件转接用的是elif,else必须放最后
案例:成绩等级判断
bash
#!/bin/bash
read -p "请输入您要检测的成绩[0-100]:" score
if [ $score -lt 0 ] || [ $score -gt 100 ];then
echo "您输入的成绩有误,请重新输入[0-100]"
elif [ $score -ge 90 ];then
echo "优秀"
elif [ $score -ge 80 ];then
echo "良好"
elif [ $score -ge 70 ];then
echo "一般"
elif [ $score -ge 60 ];then
echo "及格"
else
echo "不及格"
fi
案例:简略功能菜单
bash
[root@server day02]# vim /root/shell/day02/list.sh
#!/bin/bash
echo "输入1:查看主机名
输入2:查看IP地址
输出3:查看网关
输入4:查看磁盘
输入5:查看内存信息"
read -p "请输入您要查看的内容编号: " num
if [ $num -lt 1 ] || [ $num -gt 5 ];then
echo "您的输入有误,请重新执行"
elif [ $num -eq 1 ];then
hostname
elif [ $num -eq 2 ];then
ifconfig | head -2
elif [ $num -eq 3 ];then
route -n
elif [ $num -eq 4 ];then
lsblk
else
free -h
fi
[root@server day02]# chmod +x /root/shell/day02/list.sh
[root@server day02]# /root/shell/day02/list.sh
命令补充:free:
作用 :查看Linux物理内存、交换分区 使用情况。
用法:
free -h最常用,人性化单位显示;-m按MB、-g按GB查看;-s 1每秒刷新监控;- 看内存够不够只看 available,Swap占用高说明内存不足。
!a:执行最后一次a开头的命令
!!:执行上一条命令
三、for 循环(列表式 + C 语言风格)
for循环是有次数限制的循环。
3.1 列表式 for 循环
- 遍历/列表式循环
- 根据变量的不同取值,重复执行命令序列
(值列表中的值并不一定要被调用出来,也可以仅作为命令循环的基数,每有一个值就可以循环一次)
bash
for 变量 in 值列表 #(值列表中每一个值之间用空格隔开)
do
要执行的命令
done
- for的作用是逐个遍历 in 后面的值列表。for后会跟一个变量,值列表中的数据会赋值给这个变量。每一次循环,都会:
- 把值列表下一个元素赋值给这个变量
- 执行 do~done 里的命令序列
- 命令序列中通过 $变量 引用当前这个元素
案例1:批量创建用户
bash
#!/bin/bash
for i in james paul bella
do
useradd $i
echo 123456 | passwd --stdin $i
done
案例2:从文件读取用户批量创建
bash
#!/bin/bash
for i in $(cat /opt/user.txt)
do
useradd $i
echo 123456 | passwd --stdin $i
done
3.2 C 语言风格 for 循环
bash
for ((初值; 条件; 步长控制))
do
要执行的命令
done
案例3:1~100 求和
bash
#!/bin/bash
sum=0
for ((i=1; i<=100; i++))
do
sum=$[sum+i]
done
echo "1+2+3+...+100的整数之和为: $sum"
案例4:批量 ping 网段
bash
#!/bin/bash
for ((i=1; i<=10; i++))
do
ping -c 4 -i 0.2 -W 1 192.168.8.$i &> /dev/null
if [ $? -eq 0 ];then
echo "192.168.8.$i 通了"
else
echo "192.168.8.$i 不通"
fi
done
四、while 循环
4.1 基础语法
条件成立则循环,: 表示恒成立(死循环)。
bash
while 条件测试
do
命令序列
done
4.2 案例1:批量创建规律用户
bash
#!/bin/bash
i=1
while [ $i -le 5 ]
do
useradd testuser$i
echo 123456 | passwd --stdin testuser$i
i=$[i+1]
done
4.3 案例2:循环判断成绩(输入 quit 退出)
bash
#!/bin/bash
while :
do
read -p "请输入您要检测的成绩[0-100]:" score
if [ $score == quit ];then
echo "Bye~"
exit
elif [ $score -lt 0 ] || [ $score -gt 100 ];then
echo "您输入的成绩有误,请重新输入[0-100]"
elif [ $score -ge 90 ];then
echo "优秀"
elif [ $score -ge 80 ];then
echo "良好"
elif [ $score -ge 70 ];then
echo "一般"
elif [ $score -ge 60 ];then
echo "及格"
else
echo "不及格"
fi
done
五、Shell 随机数($RANDOM)
5.1 随机数基础
- Shell 内置随机数变量:
$RANDOM - 生成 1~10 随机数:
$[RANDOM % 10 + 1]
bash
echo $RANDOM
echo $[RANDOM % 10 + 1]
5.2 实战:猜数字游戏
bash
#!/bin/bash
num=$[RANDOM % 10 +1]
while :
do
clear
read -p "请输入您猜的数字【1-10】: " guess
if [ $guess -eq $num ];then
echo "恭喜您!猜对了"
exit
elif [ $guess -gt $num ];then
echo "很遗憾,猜大了!"
else
echo "很遗憾,猜小了!"
fi
sleep 1
done
六、全文核心总结
- 条件测试 :掌握
[ ]语法、空格规范、$?返回值规则 - 四类判断
- 字符串:
-z/-n/==/!= - 整数:
-eq/-ne/-gt/-lt/-ge/-le - 文件:
-e/-d/-f/-r/-w/-x - 多条件:
&&(与)、||(或)、;(顺序执行)
- 字符串:
- if 判断:单分支、双分支、多分支全覆盖
- 循环
- for:列表遍历、C 风格计数
- while:条件循环、死循环
- 随机数 :
$RANDOM实现随机场景,可做小游戏/批量随机任务