Shell 循环语句:for、while、until 实战详解

在 Shell 脚本中,循环语句用于重复执行一组命令,是实现“批量操作”“条件重复”的核心工具。本文围绕 for、while、until 三种循环,结合具体案例讲解语法与实战场景,并补充 break/continue 的用法。
一、for 循环:批量处理已知列表或范围
for 循环适合处理已知数据列表(如用户名单、IP 列表)或固定数值范围(如 1-10),通过“逐一读取数据”执行命令。
1. 基本语法
语法 1:遍历列表(最常用)
for 变量名 in 取值列表 # 取值列表:空格分隔的字符串/文件内容/命令结果
do
命令序列 # 对每个变量值执行的命令
done
语法 2:数值范围循环(Bash 扩展)
for ((初始值; 循环条件; 自增/自减)) # 类似其他编程语言的 for 循环
do
命令序列
done
2. 实战案例
案例 1:批量创建用户(遍历文件列表)
需求:从 users.txt 读取用户名,批量创建用户并设置统一密码。
- 第一步:创建用户列表文件
[root@ansible ~]# vim /root/users.txt # 写入以下内容,每行一个用户名 hina mika asuka role - 第二步:编写脚本
addusers.sh[root@ansible ~]# vim addusers.sh #!/bin/bash # 批量创建用户并设置密码 read -p "请输入统一密码:" PASSWD # 读取用户输入的密码 # 遍历 users.txt 中的每个用户名 for UNAME in `cat /root/users.txt` # `` 表示执行命令并获取结果 do useradd $UNAME # 创建用户 echo "$PASSWD" | passwd --stdin $UNAME # 批量设置密码 echo "$UNAME 创建成功!" # 输出结果 done - 执行脚本(需 root 权限)
[root@ansible ~]# chmod +x addusers.sh [root@ansible ~]# ./addusers.sh 请输入统一密码:123456 Changing password for user hina. passwd: all authentication tokens updated successfully. hina 创建成功! Changing password for user mika. passwd: all authentication tokens updated successfully. mika 创建成功! Changing password for user asuka. passwd: all authentication tokens updated successfully. asuka 创建成功! Changing password for user role. passwd: all authentication tokens updated successfully. role 创建成功! # 输入密码后自动创建所有用户
案例 2:数值范围循环(输出 1-10,步长控制)
需求 1:输出 1-10(步长 1,默认自增)
[root@ansible ~]# vim test1.sh
#!/bin/bash
for ((i=1; i<=10; i++)) # i 从 1 开始,<=10 时循环,每次+1
do
echo $i
done
执行脚本:
[root@ansible ~]# sh test1.sh
1
2
3
4
5
6
7
8
9
10
需求 2:输出 1-10 中的奇数(步长 2,每次+2)
[root@ansible ~]# vim test2.sh
#!/bin/bash
for ((i=1; i<=10; i+=2)) # i 每次增加 2
do
echo $i # 输出:1 3 5 7 9
done
执行脚本:
[root@ansible ~]# sh test2.sh
1
3
5
7
9
案例 3:计算 1-100 的整数和(数值循环累加)
需求:用 for 循环计算 1 到 100 的所有整数之和。
[root@ansible ~]# vim test3.sh
#!/bin/bash
sum=0 # 初始化求和变量,初始值为 0
for ((i=1; i<=100; i++))
do
sum=$((sum + i)) # 每次循环将 i 加到 sum 中($((...)) 用于算术计算)
done
echo "1-100 的整数和为:$sum" # 输出结果:5050
[root@ansible ~]# sh test3.sh
1-100 的整数和为:5050
案例 4:批量检测主机存活状态(遍历 IP 列表)
需求:从 iplist.txt 读取 IP 地址,用 ping 检测主机是否在线。
- 第一步:创建 IP 列表文件
vim /root/iplist.txt 192.168.100.10 192.168.100.20 192.168.100.30 - 第二步:编写脚本
check_ip.sh#!/bin/bash # 批量检测 IP 存活状态 ip_list=`cat /root/iplist.txt` # 读取 IP 列表 for ip in $ip_list do # ping 3 次(-c 3),超时 1 秒(-W 1),所有输出重定向到黑洞(&>/dev/null) ping -c 3 -W 1 $ip &>/dev/null if [ $? -eq 0 ]; then # $? 为上条命令返回码,0 表示成功(主机在线) echo "$ip 在线" else echo "$ip 离线" fi done
二、while 循环:条件满足时重复执行
while 循环通过“持续检测条件”实现重复执行,只要条件为真,就反复执行命令。适合处理“未知循环次数”的场景(如猜数字游戏、等待用户输入)。
1. 基本语法
while 条件测试 # 条件为真(返回码 0)时执行循环体
do
命令序列
(可选)自增/自减变量(避免无限循环)
done
2. 实战案例
案例 1:输出 0-10 的整数(条件控制循环次数)
需求:从 0 开始,每次+1,直到数值大于 10 时停止。
[root@ansible ~]# vim aa.sh
#!/bin/bash
a=0 # 初始化变量 a 为 0
while [ $a -le 10 ] # 条件:a <= 10 时循环
do
echo $a # 输出当前 a 的值
let a++ # 变量 a 自增 1(let 用于算术运算)
done
[root@ansible ~]# sh aa.sh
0
1
2
3
4
5
6
7
8
9
10
案例 2:计算 1-100 的整数和(while 累加)
需求:用 while 循环替代 for,实现 1-100 求和。
[root@ansible ~]# vim bb.sh
#!/bin/bash
sum=0 # 求和变量
n=1 # 计数器变量(从 1 开始)
while [ $n -le 100 ] # 条件:n <= 100
do
sum=$((sum + n)) # 累加
let n++ # 计数器+1
done
echo "1-100 的和为:$sum" # 输出:5050
[root@ansible ~]# sh bb.sh
1-100 的和为:5050
案例 3:随机猜数字游戏(无限循环+条件退出)
需求:生成 0-999 的随机数,让用户猜,直到猜对为止,统计猜的次数。
- 知识点:
$RANDOM是 Bash 内置变量,生成 0-32767 的随机数;expr $RANDOM % 1000可得到 0-999 的随机数。
[root@ansible ~]# vim bb.sh
#!/bin/bash
# 随机猜数字游戏(0-999)
num=$(expr $RANDOM % 1000) # 生成 0-999 的随机数
count=0 # 统计猜的次数
echo "欢迎参与猜数字游戏!数字范围:0-999"
while true # 无限循环(条件永远为真)
do
read -p "请输入你猜的数字:" n # 读取用户输入
let count++ # 次数+1
# 判断用户输入与随机数的关系
if [ $n -eq $num ]; then
echo "恭喜猜对了!正确数字是 $num"
echo "你总共猜了 $count 次"
exit 0 # 猜对后退出脚本(终止循环)
elif [ $n -gt $num ]; then
echo "猜大了!再试试~"
else
echo "猜小了!再试试~"
fi
done
执行脚本
[root@ansible ~]# sh bb.sh
欢迎参与猜数字游戏!数字范围:0-999
请输入你猜的数字:500
猜小了!请再试一试
请输入你猜的数字:750
猜小了!请再试一试
请输入你猜的数字:875
猜大了!请再试一试
请输入你猜的数字:812
猜大了!请再试一试
请输入你猜的数字:780
猜大了!请再试一试
请输入你猜的数字:765
猜小了!请再试一试
请输入你猜的数字:772
猜小了!请再试一试
请输入你猜的数字:776
猜大了!请再试一试
请输入你猜的数字:774
恭喜猜对了!正确数字是 774
你一共猜了 9 次
三、until 循环:条件不满足时重复执行
until 循环与 while 逻辑相反:只要条件为假(返回码非 0),就反复执行命令;直到条件为真时停止。适合“直到某个条件达成才停止”的场景(如等待文件创建)。
1. 基本语法
until 条件测试 # 条件为假时执行循环体,条件为真时停止
do
命令序列
done
2. 实战案例:计算 1-100 的整数和(until 实现)
需求:用 until 循环替代 while,实现 1-100 求和(条件:当 n > 100 时停止)。
[root@ansible ~]# vim cc.sh
#!/bin/bash
sum=0
n=1
# 条件:当 n > 100 时停止循环(否则继续执行)
until [ $n -gt 100 ]
do
sum=$((sum + n))
let n++
done
echo "1-100 的和为:$sum" # 输出:5050
执行脚本:
[root@ansible ~]# sh cc.sh
1-100 的和为: 5050
四、双 for 循环:循环嵌套
双 for 循环即“循环内部嵌套另一个循环”,外层循环控制“大范围”,内层循环控制“小范围”,适合处理“矩阵式”数据(如打印九九乘法表、多层目录创建)。
1. 基础示例:嵌套循环输出
[root@ansible ~]# vim dd.sh
#!/bin/bash
# 双 for 循环:外层控制 a(1-5),内层控制 b(1-5)
for ((a=1; a<=5; a++))
do
echo "外层循环:a = $a"
for ((b=1; b<=5; b++))
do
echo " 内层循环:b = $b" # 缩进体现层级
done
done
执行结果:
[root@ansible ~]# sh dd.sh
外层循环: a =1
内层循环: b =1
内层循环: b =2
内层循环: b =3
内层循环: b =4
内层循环: b =5
外层循环: a =2
内层循环: b =1
内层循环: b =2
内层循环: b =3
内层循环: b =4
内层循环: b =5
外层循环: a =3
内层循环: b =1
内层循环: b =2
内层循环: b =3
内层循环: b =4
内层循环: b =5
外层循环: a =4
内层循环: b =1
内层循环: b =2
内层循环: b =3
内层循环: b =4
内层循环: b =5
外层循环: a =5
内层循环: b =1
内层循环: b =2
内层循环: b =3
内层循环: b =4
内层循环: b =5
2. 实战:打印九九乘法表
需求:用双 for 循环打印九九乘法表(外层控制行数,内层控制列数)。
[root@ansible ~]# vim 99.sh
#!/bin/bash
# 打印九九乘法表
for ((i=1; i<=9; i++)) # 外层循环:行数(1-9)
do
for ((j=1; j<=i; j++)) # 内层循环:列数(1-当前行数)
do
echo -n "$j × $i = $((j*i)) " # -n 不换行,保持同一行输出
done
echo # 每行结束后换行
done
执行结果:
1 × 2 = 2 2 × 2 = 4 [root@ansible ~]# sh 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
五、循环控制:break 与 continue
break 和 continue 用于在循环中控制流程,避免不必要的循环执行。
1. break:跳出当前循环
- 作用:立即终止当前所在的循环(若嵌套循环,只跳出内层循环,外层继续)。
- 示例:内层循环到
b=4时跳出,外层继续执行。
[root@ansible ~]# vim dd.sh
#!/bin/bash
for ((a=1; a<=5; a++)) # 外层循环
do
echo "外层循环:a = $a"
for ((b=1; b<=5; b++)) # 内层循环
do
if [ $b -eq 4 ]; then # 当 b=4 时
break # 跳出内层循环(不再执行 b=4、b=5)
fi
echo " 内层循环:b = $b"
done
done
执行结果(内层只到 b=3):
[root@ansible ~]# sh dd.sh
外层循环: a = 1
内层循环: b =1
内层循环: b =2
内层循环: b =3
外层循环: a = 2
内层循环: b =1
内层循环: b =2
内层循环: b =3
外层循环: a = 3
内层循环: b =1
内层循环: b =2
内层循环: b =3
外层循环: a = 4
内层循环: b =1
内层循环: b =2
内层循环: b =3
外层循环: a = 5
内层循环: b =1
内层循环: b =2
内层循环: b =3
2. continue:跳过当前迭代,继续下一次
- 作用:跳过当前循环的剩余命令,直接进入下一次循环(不终止整个循环)。
- 示例:跳过 6-9 的数字,输出 1-5 和 10-15。
[root@ansible ~]# vim ee.sh
#!/bin/bash
for ((a=1; a<=15; a++))
do
if [ $a -gt 5 ] && [ $a -lt 10 ]; then # 当 a 在 6-9 之间时
continue # 跳过当前迭代(不执行 echo),直接进入下一次循环
fi
echo "当前数字:$a"
done
执行结果:
[root@ansible ~]# sh ee.sh
当前数字: 1
当前数字: 2
当前数字: 3
当前数字: 4
当前数字: 5
当前数字: 10
当前数字: 11
当前数字: 12
当前数字: 13
当前数字: 14
当前数字: 15
总结
| 循环类型 | 核心场景 | 语法特点 |
|---|---|---|
for | 已知列表(用户/IP)、固定数值范围 | 遍历列表或 ((初始值; 条件; 自增)) |
while | 未知循环次数,条件为真时执行 | while 条件; do ... done |
until | 未知循环次数,条件为假时执行 | until 条件; do ... done(与 while 相反) |
| 双循环 | 矩阵数据(乘法表、多层操作) | 循环嵌套,外层控范围,内层控细节 |
循环控制要点:
break:跳出当前循环(嵌套时只跳内层);continue:跳过当前迭代,继续下一次;- 避免无限循环:确保循环内有“变量自增/条件变化”(如
let i++)。
掌握这些循环用法,可轻松实现批量创建、状态检测、数据计算等自动化任务,大幅提升运维效率。

4323

被折叠的 条评论
为什么被折叠?



