一、前言
在 Shell 脚本编程中,循环 是处理重复任务的核心结构。而当需要处理二维数据、多层结构或组合任务时,嵌套循环(Nested Loops) 就显得尤为重要。
本文将通过 5 个实用的嵌套循环应用案例 ,带你深入理解 for
、while
等循环在 Shell 中的嵌套使用方式,并附上完整可运行的脚本代码,帮助你掌握 Shell 脚本中嵌套循环的实际应用场景。
二、Shell 中的循环结构回顾
Shell 支持多种循环结构,最常用的是:
for
循环while
循环until
循环
嵌套循环即在一个循环体内再包含另一个循环,常用于处理矩阵、生成组合、遍历目录结构等场景。
三、嵌套循环语法结构
1. for 嵌套 for
bash
for i in {1..3}; do
for j in {a..c}; do
echo "i=$i, j=$j"
done
done
2. while 嵌套 while
bash
i=1
while [ $i -le 3 ]; do
j=1
while [ $j -le 3 ]; do
echo "i=$i, j=$j"
j=$((j + 1))
done
i=$((i + 1))
done
四、实战应用案例
✅ 案例一:打印乘法表(9×9)
需求:使用嵌套循环打印标准的九九乘法表。
bash
#!/bin/bash
echo "九九乘法表:"
for i in {1..9}; do
for j in $(seq 1 $i); do
result=$((i * j))
printf "%d×%d=%-2d " $j $i $result
done
echo "" # 换行
done
📌 输出示例:
1×1=1
1×2=2 2×2=4
1×3=3 2×3=6 3×3=9
...
💡 技巧:使用
printf
格式化输出,%-2d
表示左对齐两位整数。
✅ 案例二:批量创建用户与组
需求:为多个部门(dev、ops、test)分别创建 3 个用户(user1~user3),即共 9 个用户。
bash
#!/bin/bash
groups=("dev" "ops" "test")
users=("user1" "user2" "user3")
for group in "${groups[@]}"; do
# 检查组是否存在,不存在则创建
if ! getent group $group > /dev/null; then
groupadd $group
echo "已创建组: $group"
fi
for user in "${users[@]}"; do
# 检查用户是否存在
if ! id "$user" &>/dev/null; then
useradd -m -g $group $user
echo "已创建用户: $user,属于组: $group"
else
echo "用户 $user 已存在"
fi
done
done
⚠️ 注意:此脚本需以 root 权限运行。
✅ 案例三:遍历多级目录并统计文件数量
需求 :遍历指定的多个目录(如 /home
, /var
, /tmp
),并在每个目录中统计各类文件(普通文件、目录、链接等)的数量。
bash
#!/bin/bash
dirs=("/home" "/var" "/tmp")
for dir in "${dirs[@]}"; do
if [ ! -d "$dir" ]; then
echo "目录不存在: $dir"
continue
fi
echo "=== 统计目录: $dir ==="
file_count=0
dir_count=0
link_count=0
for item in "$dir"/*; do
if [ -f "$item" ]; then
((file_count++))
elif [ -d "$item" ]; then
((dir_count++))
elif [ -L "$item" ]; then
((link_count++))
fi
done
echo "普通文件: $file_count"
echo "子目录: $dir_count"
echo "符号链接: $link_count"
echo ""
done
✅ 案例四:生成测试数据文件(组合命名)
需求 :为测试环境生成一系列文件,格式为 data_<部门>_<编号>.txt
,例如 data_dev_01.txt
。
bash
#!/bin/bash
departments=("sales" "hr" "finance")
numbers=(01 02 03)
for dept in "${departments[@]}"; do
for num in "${numbers[@]}"; do
filename="data_${dept}_${num}.txt"
echo "生成测试文件: $filename"
echo "测试数据 - 部门: $dept, 编号: $num" > "$filename"
done
done
echo "✅ 所有测试文件生成完成!"
✅ 案例五:检查服务端口连通性(主机 × 端口)
需求:对多台服务器的多个关键端口(如 22、80、443)进行连通性测试。
bash
#!/bin/bash
hosts=("192.168.1.10" "192.168.1.11" "10.0.0.5")
ports=(22 80 443)
for host in "${hosts[@]}"; do
echo "=== 检查主机: $host ==="
for port in "${ports[@]}"; do
timeout 3 bash -c "echo > /dev/tcp/$host/$port" 2>/dev/null
if [ $? -eq 0 ]; then
echo "✅ $host:$port 开放"
else
echo "❌ $host:$port 不可达"
fi
done
echo ""
done
💡 说明:
/dev/tcp/host/port
是 Bash 内置功能,用于 TCP 连接测试(需启用)。
五、嵌套循环使用技巧与注意事项
技巧 | 说明 |
---|---|
使用 break 和 continue |
break 2 可跳出两层循环;continue 跳过当前迭代 |
避免深层嵌套 | 超过 3 层建议拆分为函数 |
合理使用数组 | 配合数组可提高代码可读性 |
加日志输出 | 便于调试和监控执行流程 |
注意性能 | 多层循环可能导致 O(n²) 时间复杂度 |
六、总结
应用场景 | 推荐循环结构 |
---|---|
数学表格生成 | for 嵌套 for |
批量用户/文件操作 | for 嵌套 for |
目录遍历统计 | for 嵌套 for 或 while |
网络连通性测试 | for 嵌套 for |
多维数据处理 | 嵌套循环 + 函数封装 |
嵌套循环是 Shell 脚本中处理复杂任务的利器。通过本文的 5 个案例,你应该已经掌握了:
✅ 如何编写嵌套循环
✅ 常见应用场景
✅ 实际运维中的实用技巧
✅ 如何避免常见错误
七、结语
感谢您的阅读!如果你有任何疑问或想要分享的经验,请在评论区留言交流!