# Linux Shell 编程入门 Day02:条件测试、if 判断、循环与随机数

课前拓展: 我们都知道布尔值(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 文件名 文件存在 且 是普通文件
    • -d 目录名 目录存在 且 是目录
      因此-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物理内存、交换分区 使用情况。
用法:

  1. free -h 最常用,人性化单位显示;
  2. -m 按MB、-g 按GB查看;
  3. -s 1 每秒刷新监控;
  4. 看内存够不够只看 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

六、全文核心总结

  1. 条件测试 :掌握 [ ] 语法、空格规范、$? 返回值规则
  2. 四类判断
    • 字符串:-z/-n/==/!=
    • 整数:-eq/-ne/-gt/-lt/-ge/-le
    • 文件:-e/-d/-f/-r/-w/-x
    • 多条件:&&(与)、||(或)、;(顺序执行)
  3. if 判断:单分支、双分支、多分支全覆盖
  4. 循环
    • for:列表遍历、C 风格计数
    • while:条件循环、死循环
  5. 随机数 :$RANDOM 实现随机场景,可做小游戏/批量随机任务
相关推荐
YYRAN_ZZU2 分钟前
GMSL开发加解串配置介绍
linux·嵌入式硬件
墨家前任巨子11 分钟前
定时关机脚本
运维
云计算练习生11 分钟前
什么是上下文切换?进程切换时 CPU 到底在保存什么
linux·服务器·操作系统·进程切换
用户05101225729612 分钟前
RGA(二)——RK3588 的核拓扑与能力差异
linux·嵌入式
ESDWAN13 分钟前
企业组网后网络频繁掉线,常见故障排查指南
运维·网络·架构
用户05101225729614 分钟前
RGA(一)——基础知识
linux·嵌入式
qetfw18 分钟前
Debian 综合服务实训:Apache2、Samba、LDAP、vsftpd 与 OpenVPN
linux·服务器·debian
用户05101225729618 分钟前
RGA(三)——实宽高、虚宽高与对齐约束
linux·嵌入式
fastjson_28 分钟前
帆软看板 - 问题收集
linux·前端·javascript
jianpeng的工程笔记31 分钟前
EL8 / EL9 安装 Slurm 26.05.4:主备控制器、MariaDB 记账与作业验收
linux·数据库·mariadb·高性能计算·slurm