# 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 文件名 \] **文件存在 且 是普通文件**

      因此-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 实现随机场景,可做小游戏/批量随机任务
相关推荐
木雷坞1 小时前
视觉算法环境 Docker 镜像拉取失败排查
运维·人工智能·docker·容器
郝亚军1 小时前
ubuntu 22.04如何安装libmodbus
运维·服务器·ubuntu
李日灐1 小时前
< 6 > Linux 自动化构建工具:makefile 详解 + 进度条实战小项目
linux·运维·服务器·后端·自动化·进度条·makefile
JZC_xiaozhong2 小时前
跨系统审批自动化怎么做?从采购到销售合同的完整方案
大数据·运维·自动化·流程自动化·数据集成与应用集成·业务流程管理·异构数据集成
嵌入式×边缘AI:打怪升级日志2 小时前
嵌入式Linux开发:开源组件、第三方库与许可证详解
linux
计算机安禾2 小时前
【Linux从入门到精通】第34篇:搭建FTP与Samba——跨平台文件共享解决方案
linux·运维·服务器
日取其半万世不竭2 小时前
用 Netdata 实时监控服务器,比 Prometheus + Grafana 轻量得多
linux·服务器·网络·系统架构·负载均衡·zabbix·grafana
jamon_tan2 小时前
Linux下cmake构建方法
linux
JiaWen技术圈2 小时前
内核子系统 nf_tables 深度解析
linux·服务器·安全·运维开发