【运维进阶】case、for、while、until语句大合集
case、for、while、until语句大合集
case 条件语句的应用实践
case 条件语句的语法
case 条件语句的语法格式为:
case 变量 in模式1)命令序列1;;模式2|模式3)命令序列2;;*)默认命令序列;;
esac
变量:通常是脚本传入的参数,如 $1
。
模式:支持字符串、通配符(*
、?
)、多个模式(a|b|c
)。
;;
:表示该分支结束。
*
:相当于 default
,匹配不到时执行。
esac
:表示 case
语句结束(反过来的 case
)。
为了便于大家记忆,下面是某女生写的case 条件语句的中文形象描述:
case "找老公条件" in资产大于1千万)嫁给你;;资产介于1百万和1千万之间)再考虑以下;;资产小于1百万)再见;;其他情况)视情况而定;;
esac
case 条件语句实践
**示例:**模拟 Linux 服务管理脚本的实现
# 服务管理脚本1
# 用 case...esac 语句来控制 sshd 服务的 启动、停止和状态查看。
[root@controller bin 20:12:44]# vim case1_sshd
[root@controller bin 20:12:51]# cat case1_sshd
#!/bin/bash
case $1 instart)systemctl start sshd;;stop)systemctl stop sshd;;status)systemctl status sshd;;*)echo "Usage: $0 start | stop | status";;
esac# 根据传入的第一个参数($1)来决定执行哪一个分支。
# 如果参数不是 start|stop|status,就打印提示用法。# 执行脚本时不加参数
# 走到了 *) 分支,提示加参数。
[root@controller bin 20:13:08]# bash case1_sshd
Usage: case1_sshd start | stop | status
[root@controller bin 20:13:16]# bash case1_sshd stop
[root@controller bin 20:13:20]# bash case1_sshd status
● sshd.service - OpenSSH server daemonLoaded: loaded (/usr/lib/systemd/system/sshd.service; enabled; vendor
preset: enabled)Active: inactive (dead) since 日 2025-08-24 20:13:20 CST; 4s agoDocs: man:sshd(8)man:sshd_config(5)
...
[root@controller bin 20:13:35]# bash case1_sshd start
[root@controller bin 20:13:53]# bash case1_sshd status
● sshd.service - OpenSSH server daemonLoaded: loaded (/usr/lib/systemd/system/sshd.service; enabled; vendor preset: enabled)Active: active (running) since 日 2025-08-24 20:13:53 CST;
...
# 服务管理脚本2
# 模式合并(start|stop|status)来减少重复代码。
[root@controller bin 20:16:38]# vim case2_sshd
[root@controller bin 20:16:47]# cat case2_sshd
#!/bin/bash
case $1 instart|stop|status)systemctl $1 sshd # 用 $1 直接把参数传给systemctl,一行就能搞定三个情况。;;*)echo "Usage: $0 start | stop | status";;
esac[root@controller bin 20:16:55]# bash case2_sshd
Usage: case2_sshd start | stop | status
[root@controller bin 20:17:21]# bash case2_sshd stop
[root@controller bin 20:17:29]# bash case2_sshd status
● sshd.service - OpenSSH server daemonLoaded: loaded (/usr/lib/systemd/system/sshd.service; enabled; vendor preset: enabled)Active: inactive (dead) since 日 2025-08-24 20:17:29 CST; 3s agoDocs: man:sshd(8)man:sshd_config(5)
...
[root@controller bin 20:17:39]# bash case2_sshd start
[root@controller bin 20:17:51]# bash case2_sshd status
● sshd.service - OpenSSH server daemonLoaded: loaded (/usr/lib/systemd/system/sshd.service; enabled; vendor preset: enabled)Active: active (running) since 日 2025-08-24 20:17:51 CST; 1s agoDocs: man:sshd(8)man:sshd_config(5)
...
case 语句核心总结
- 核心特点:
- 适用于多分支判断场景
- 比 if…elif…else 结构更简洁直观
- 语法格式固定:case 变量 in … 分支 … esac
- 典型应用场景:
- 菜单选择:交互式脚本中处理用户输入的选项
- 参数处理:解析命令行参数(如 -h、-v 等选项)
- 服务管理:处理服务的 start/stop/restart/status 等指令
- 优势:
- 逻辑层次清晰,便于维护
- 减少冗余判断代码
- 对固定值匹配场景适配性强
for 循环语句的应用实践
for循环语句和while循环语句类似,但for循环语句主要用于执行次数有限的循环,而不是用于守护进程及无限循环。
for 循环语法结构
Shell 脚本中 for
循环的两种语法结构及说明:
一、变量取值型(列表遍历式)
语法结构
for 变量名 in 变量取值列表
do指令...
done
关键说明
-
结构特点:
- 通过
in
关键字指定变量的取值列表(元素以空格分隔) - 可省略
in 变量取值列表
,此时默认等价于in "$@"
(即遍历脚本的位置参数)
- 通过
-
执行流程:
- 变量依次获取列表中的每个值
- 每次取值后执行
do
和done
之间的循环指令 - 直到取完列表中所有值,循环结束
-
示例:
# 遍历指定列表 for fruit in apple banana orange doecho "当前水果:$fruit" done# 省略列表(等价于 in "$@") for arg doecho "参数:$arg" done
二、C 语言型(表达式控制式)
语法结构
for ((exp1; exp2; exp3))
do指令...
done
关键说明
-
表达式含义:
exp1
:变量初始化(如i=0
)exp2
:循环条件判断(如i<10
)exp3
:变量迭代操作(如i++
或i--
)
-
执行流程:
- 先执行
exp1
初始化变量 - 判断
exp2
是否成立:成立则执行循环体,不成立则退出循环 - 每次循环结束后执行
exp3
更新变量,再重复判断exp2
- 先执行
-
示例:
# 计数从1到5 for ((i=1; i<=5; i++)) doecho "计数:$i" done
两种结构对比:
- 变量取值型:适合遍历已知列表(如文件列表、参数列表)
- C 语言型:适合需要精确控制循环次数的场景(如固定范围计数)
for循环结构执行流程对应的逻辑图如下:
for 循环语句的基础实践
示例1:三对情侣参加婚礼
3个新郎为A、B、C,3个新娘为X、Y、Z。有人想知道究竟谁与谁结婚,于是就问新人中的三位,得到如下结果:
- A说他将和X结婚;
- X说她的未婚夫是C;
- C说他将和Z结婚。
这人事后知道他们说的全是假话。那么,究竟谁与谁结婚呢?
[root@controller bin 20:36:20]# vim marry.sh
[root@controller bin 20:36:29]# cat marry.sh
#!/bin/bash
# 外层循环:为A选择配偶,从X、Y、Z中取值
for A in X Y Z
do# 中层循环:为B选择配偶,从X、Y、Z中取值for B in X Y Zdo# 内层循环:为C选择配偶,从X、Y、Z中取值for C in X Y Zdo# 条件判断:筛选符合所有规则的组合# 1. A、B、C的配偶必须互不相同(三个不等条件)# 2. A的配偶不能是X# 3. C的配偶不能是X# 4. C的配偶不能是Zif [ "$A" != "$B" -a "$A" != "$C" -a "$B" != "$C" -a "$A" != "X" -a "$C" != "X" -a "$C" != "Z" ];then# 输出符合条件的组合echo A 与 $A 结婚echo B 与 $B 结婚echo C 与 $C 结婚fidonedone
done# 执行
[root@controller bin 20:36:47]# bash marry.sh A 与 Z 结婚B 与 X 结婚C 与 Y 结婚
示例2:九九乘法表
[root@controller bin 16:10:08]# vim 99.sh
[root@controller bin 16:10:59]# cat 99.sh
#!/bin/bash
# 外层for循环(变量取值型):控制乘法表的“行数”(即第二个乘数)
# {1..9}是Shell的序列表达式,等价于1 2 3 ... 9,num1依次取1到9的值
for num1 in {1..9}
do# 内层for循环(C语言型):控制每行的“列数”(即第一个乘数)# 初始值num2=1,循环条件num2<=num1(保证每行列数不超过行数,避免重复),每次循环num2自增1for ((num2=1;num2<=num1;num2++))do# 输出乘法表达式:-e启用转义字符,-n不自动换行(让同一行内容连在一起)# $num2*$num1:显示“第一个乘数*第二个乘数”的格式# $[ num2 * num1 ]:Shell算术扩展,计算num2和num1的乘积(等价于$((num2*num1)))# \t:插入制表符,让每行内容对齐(避免因数字位数不同导致错乱)echo -en "$num2*$num1=$[ num2 * num1 ]\t"done# 内层循环结束后,执行一次空echo:手动换行,让下一行从新的一行开始echo
done# 执行
[root@controller bin 16:11:05]# bash 99.sh
1*1=1
1*2=2 2*2=4
1*3=3 2*3=6 3*3=9
1*4=4 2*4=8 3*4=12 4*4=16
1*5=5 2*5=10 3*5=15 4*5=20 5*5=25
1*6=6 2*6=12 3*6=18 4*6=24 5*6=30 6*6=36
1*7=7 2*7=14 3*7=21 4*7=28 5*7=35 6*7=42 7*7=49
1*8=8 2*8=16 3*8=24 4*8=32 5*8=40 6*8=48 7*8=56 8*8=64
1*9=9 2*9=18 3*9=27 4*9=36 5*9=45 6*9=54 7*9=63 8*9=72 9*9=81
while 循环和 until 循环的应用实践
当型和直到型循环语法
while 循环语句
while 循环是 Shell 脚本中用于 “条件成立时重复执行操作” 的循环结构,核心逻辑是 “先判断条件,条件满足才执行循环”,具体说明如下:
while 循环语句的基本语法为:
while <条件表达式>
do指令...
done
提示:注意代码缩进(比如循环体指令缩进 2-4 个空格),能让代码逻辑更清晰,方便后续阅读和维护。
核心执行逻辑
- 先判断,再执行:循环启动后,会先检查
while
后面的<条件表达式>
是否成立(比如 “变量 i 小于 10”“文件存在” 等)。 - 条件成立则执行循环体:如果条件表达式结果为 “真”,就会执行
do
和done
之间的所有 “指令”(这部分叫循环体)。 - 循环判断,直到条件不成立:每次执行完循环体里的所有指令、走到
done
时,会再次回到while
处重新判断条件;只要条件还成立,就重复执行循环体,直到某一次判断时条件不成立,才会跳出循环,继续执行done
后面的代码。 - 初始条件不成立则不进循环:如果第一次判断条件时,表达式结果就是 “假”,那么循环体(
do
到done
之间的内容)会直接跳过,一句指令都不执行。
形象化理解(中文场景举例)
用日常生活场景类比,能更直观记住 while 循环的逻辑,比如 “是否继续和男朋友相处” 的判断:
# 逻辑:只要“男朋友努力工作”这个条件成立,就执行“继续相处”的操作
while 男朋友努力工作
do继续相处
done
这里的逻辑和代码完全对应:先看 “男朋友努力工作” 是否为真,是就 “继续相处”;每次 “相处” 后,会再检查一次这个条件,只要条件还满足就一直相处,直到条件不满足(比如男朋友不努力了),就停止 “继续相处”。
while 循环执行流程对应的逻辑图如下:
until 循环语句
until 循环是 Shell 脚本中与 while 循环逻辑相反的循环结构,核心特点是 “条件不成立时重复执行,条件成立时停止”,可以理解为 “直到条件满足才退出循环”,具体说明如下:
一、基本语法
until <条件表达式>
do指令...
done
二、核心执行逻辑
- 先判断条件,不成立才执行:循环启动后,首先检查
until
后面的<条件表达式>
是否成立。 - 条件不成立则进入循环体:如果条件表达式结果为 “假”(不成立),就会执行
do
和done
之间的 “指令”(即循环体);如果条件一开始就成立,循环体则会直接跳过,一句指令都不执行。 - 循环判断,直到条件成立:每次执行完循环体的所有指令、走到
done
时,会再次返回until
处重新判断条件;只要条件仍然不成立,就重复执行循环体,直到某一次判断时条件 “成立”(结果为真),才会立即跳出循环,继续执行done
之后的代码。
简单来说,until 循环的逻辑是:“只要条件没满足,就一直做;等条件满足了,就不做了”,这是它和 while 循环(“条件满足才做,不满足就不做”)最核心的区别。
三、形象化理解(中文场景举例)
用日常生活中的 “是否继续相处” 场景类比,能更直观记住 until 循环的逻辑,比如通过 “男朋友是否不努力工作” 来决定是否停止相处:
# 逻辑:直到“男朋友不努力工作”这个条件成立,才停止“继续相处”;只要这个条件不成立(男朋友努力),就一直相处
until 男朋友不努力工作
do继续相处
done
这里的逻辑和代码完全对应:先看 “男朋友不努力工作” 是否成立 —— 如果不成立(说明男朋友在努力),就 “继续相处”;每次 “相处” 后,会再检查一次条件,只要 “男朋友不努力” 这个条件没出现,就一直相处;直到某一次发现 “男朋友不努力工作”(条件成立),就停止 “继续相处”,跳出循环。
until 循环执行流程对应的逻辑图如下:
当型和直到型循环的基本范例
示例:
[root@controller bin 21:31:18]# vim target.sh
[root@controller bin 21:31:26]# cat target.sh
#!/bin/bash
# 定义目标金额变量target,设定为10000000(即1000万,作为循环停止的条件阈值)
target=10000000
# 定义当前金额变量money,初始值设为0(表示一开始没有钱)
money=0# until循环:判断条件为“当前金额>=目标金额”
# 核心逻辑:只要条件不成立(money < 1000万),就反复执行循环体;直到条件成立(money >= 1000万),停止循环
until (($money>=$target))
do# 循环体指令1:输出工作赚钱的提示信息,模拟“正在努力赚钱”的过程echo "I'm working hard to get money..."# 循环体指令2:sleep 1 表示暂停1秒再执行后续代码,模拟赚钱需要消耗时间的过程sleep 1# 循环体指令3:更新当前金额,每次在原有money基础上增加1000000(即100万)# $[ 表达式 ] 是Shell算术扩展语法,用于计算“money + 1000000”的结果并赋值给moneymoney=$[ money + 1000000 ]# 循环体指令4:输出当前最新的金额,让用户看到赚钱进度echo "I have $money."
done# 循环结束后执行的指令:当money >= 1000万时,跳出循环,输出“jiejiejie”(模拟达成目标后的欢呼)
echo jiejiejie# 执行
[root@controller bin 21:31:39]# bash target.sh
I'm working hard to get money...
I have 1000000.
I'm working hard to get money...
I have 2000000.
I'm working hard to get money...
I have 3000000.
I'm working hard to get money...
I have 4000000.
I'm working hard to get money...
I have 5000000.
I'm working hard to get money...
I have 6000000.
I'm working hard to get money...
I have 7000000.
I'm working hard to get money...
I have 8000000.
I'm working hard to get money...
I have 9000000.
I'm working hard to get money...
I have 10000000.
jiejiejie