news 2026/2/16 10:40:04

【Linux 基础知识系列:第二百零一篇】Bash 循环结构进阶:for、while 与 until

作者头像

张小明

前端开发工程师

1.2k 24
文章封面图
【Linux 基础知识系列:第二百零一篇】Bash 循环结构进阶:for、while 与 until

一、简介:为什么循环是 Shell 的“发动机”?

  • Shell 是 Linux 的胶水语言,循环结构负责“重复”——批量处理文件、轮询接口、守护进程、自动重试。

  • 实际场景

    • 一晚备份 500 个数据库 →for循环拼接文件名

    • 等待数据库端口存活 →while循环+sleep

    • 服务异常则一直重启 →until循环探测成功才退出

掌握for / while / until的语法差异与最佳实践,是运维、DevOps、开发者的基本功,也是写“不翻车”脚本的分水岭


二、核心概念:3 种循环一句话记住

循环关键词判断逻辑典型场景
for遍历列表列表耗尽即结束批量文件、固定次数
while条件为真入口判断,真→继续轮询、守护、读取管道
until条件为假入口判断,假→继续等待成功、自动重试

口诀:for 遍历,while 真继续,until 假继续


三、环境准备:3 分钟搞定实验沙箱

  1. 系统
    Ubuntu 20.04+/CentOS 8+/Debian 11+(Bash ≥ 4.3 即可)

  2. 权限
    普通用户可完成 90% 实验;文件系统演示需chmod +x

  3. 实验目录

    mkdir -p ~/bash-loop-lab && cd ~/bash-loop-lab
  4. 确认 Bash

    echo $BASH_VERSION # ≥ 4.3 支持关联数组、关联索引

四、实际案例与步骤:5 大关卡由浅入深

每个脚本均可直接复制,保存后chmod +x xxx.sh && ./xxx.sh跑通。


4.1 for 循环:批量重命名 + 安全前缀

需求:把 200 个.log文件加上日期前缀,防止覆盖。

#!/usr/bin/env bash # file: 01-rename.sh set -euo pipefail date_prefix=$(date +%F) for file in *.log; do [[ -f $file ]] || continue # 空目录保护 new="${date_prefix}_${file}" echo "mv $file $new" mv "$file" "$new" done echo "批量重命名完成"

技巧点

  • for file in *.log避免$(ls *.log)空格裂开的坑。

  • continue跳过目录/空匹配,脚本鲁棒性↑。


4.2 C 风格 for:固定次数倒计时

需求:脚本升级前倒计时 5 秒,可中途取消。

#!/usr/bin/env bash # file: 02-countdown.sh for ((i=5;i>0;i--)); do printf '\r升级将在 %d 秒后开始 ... 按 Ctrl+C 取消' "$i" sleep 1 done printf '\r开始升级! \n'

说明

  • 双括号(())内变量无需$前缀,支持++ -- +=

  • printf \r实现同一行动态刷新,界面友好。


4.3 while 循环:端口未就绪就等待

需求:数据库 3306 端口监听前一直重试,每 2 秒检测一次。

#!/usr/bin/env bash # file: 03-wait-port.sh HOST=127.0.0.1 PORT=3306 TIMEOUT=300 count=0 echo "等待 $HOST:$PORT 就绪 ..." while ! nc -z "$HOST" "$PORT"; do ((count++)) if [[ $count -gt $((TIMEOUT/2)) ]]; then echo "超时退出" >&2; exit 1 fi sleep 2 done echo "端口已就绪,继续执行业务 SQL ..."

依赖

  • nc(nmap-ncat):sudo dnf/apt install -y nc


4.4 until 循环:服务异常则一直重启

需求:Spring Boot jar 异常退出后 5 秒自动重启,直到手动 Ctrl+C。

#!/usr/bin/env bash # file: 04-until-restart.sh JAR=myapp.jar LOG=app.log until java -jar "$JAR" >> "$LOG" 2>&1; do echo "$(date) 服务异常退出,5 秒后重启" >&2 sleep 5 done echo "$(date) 服务正常退出,不再重启"

要点

  • until判断最后一条命令退出码,非 0 就继续循环。

  • 适合“成功即跳出”场景,逻辑比while true更清晰。


4.5 嵌套循环:批量创建目录+文件

需求:生成proj1/{src,doc,test}共 3×3=9 个目录,并在每个目录放 README.md。

#!/usr/bin/env bash # file: 05-nested.sh projects=(proj1 proj2 proj3) folders=(src doc test) for p in "${projects[@]}"; do for f in "${folders[@]}"; do dir="$p/$f" mkdir -p "$dir" echo "# $dir" > "$dir/README.md" done done echo "项目骨架生成完成"

技巧

  • 用数组+双引号避免空格分割;嵌套层级直观。


4.6 循环读取文件:行内空格安全

需求:逐行读取ip.list(格式:IP 端口),检测连通性。

#!/usr/bin/env bash # file: 06-readfile.sh INPUT=ip.list # 方式1:while read 最安全 while IFS= read -r line; do [[ -z "$line" || "$line" == \#* ]] && continue # 跳过空行与注释 ip=${line% *} port=${line#* } if nc -z "$ip" "$port"; then echo "$ip:$port OK" else echo "$ip:$port FAIL" >&2 fi done < "$INPUT"

对比

  • for i in $(cat file)会把行内空格拆成多词 →禁止

  • while read+IFS=保留原始行,100% 安全


4.7 关联数组+for:按分组批量杀进程

需求:按服务名(nginx、php、redis)分组优雅重启。

#!/usr/bin/env bash # file: 07-kill-group.sh declare -A groups=( [web]="nginx php-fpm" [cache]="redis-server" ) for group in "${!groups[@]}"; do echo "=== 重启 $group ===" for proc in ${groups[$group]}; do pkill -USR2 "$proc" # 示例信号,可换 systemctl done done

要求
Bash 4.0+ 支持关联数组;检查版本echo $BASH_VERSION


五、常见问题与解答(FAQ)

问题现象解决
Syntax error: bad for loop variableDash 执行 C 风格for ((;;))指定#!/usr/bin/env bash
ls: cannot access '*.log': No such file or directory空目录展开用 `for file in *.log; do [[ -f $file ]]continue; ...`
死循环 CPU 100%while 内无 sleepsleep 1read -t 1
read 丢失最后一行文件末尾无\n`while read -r line[[ -n $line ]]; do ... done`
变量修改在子 shell 无效管道后while用重定向< fileshopt -s lastpipe

六、实践建议与最佳实践

  1. set -euo pipefail 黄金三件套
    让脚本在变量未定义、管道失败、循环退出码非 0 时立刻失败,避免“静默继续”。

  2. 用数组+双引号代替ls

    files=(*.log) for f in "${files[@]}"; do ...
  3. 循环内打印进度

    printf '\r处理中 %d/%d' "$i" "$total"
  4. 超时退出
    自带计数器或timeout命令,防止死循环。

  5. 调试技巧

    • bash -x script.sh看每次循环变量值。

    • set +x/set -x局部开关,减少刷屏。

  6. 性能优化

    • 大量文件优先find ... -print0 | while IFS= read -r -d '' file; do ...

    • 避免在循环里cat | grep | awk三连,改用 Bash 内置参数替换。


七、总结:一张脑图带走全部要点

Bash 循环 ├─ for:列表遍历 / C 风格计数 ├─ while:条件真继续(轮询) ├─ until:条件假继续(重试) ├─ 嵌套:多级目录、多项目 ├─ read:行内空格安全 └─ 黄金习惯:引号 + -euo pipefail + 超时

掌握for / while / until语法差异、安全写法、调试技巧,你就拥有了:

  • 批量自动化的瑞士军刀:文件改名、备份、部署脚本 10 行搞定。

  • 服务守护的坚固盾牌:端口等待、异常重启、日志监控不再手写死循环。

  • 跨平台兼容的移植指南:避开$(ls)for i in $(cat file)等经典陷阱。

立刻打开终端,把本文脚本复制到~/bash-loop-lab,跑一遍、改一遍、拆一遍,写属于自己的第一个健壮循环!祝你玩得开心,循环永不死。

版权声明: 本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若内容造成侵权/违法违规/事实不符,请联系邮箱:809451989@qq.com进行投诉反馈,一经查实,立即删除!
网站建设 2026/2/14 11:12:27

深度剖析GEO优化技术:AI搜索浪潮下的推广创新策略

2025年&#xff0c;用户获取信息的方式正在改变。当企业还在为搜索广告的高成本和传统SEO的漫长周期发愁时&#xff0c;AI搜索平台已悄然成为新的流量入口。GEO优化&#xff08;生成式引擎优化&#xff09;应运而生&#xff0c;它让企业信息在AI回答中被推荐&#xff0c;而不是…

作者头像 李华
网站建设 2026/2/9 21:52:04

EmotiVoice语音合成在图书馆自助服务系统中的便捷应用

EmotiVoice语音合成在图书馆自助服务系统中的便捷应用 在一座现代化的智慧图书馆里&#xff0c;一位视障读者轻轻触碰自助终端屏幕&#xff0c;询问&#xff1a;“《平凡的世界》在哪里&#xff1f;”几秒钟后&#xff0c;一个温和、清晰且略带关切语气的声音响起&#xff1a;“…

作者头像 李华
网站建设 2026/2/13 7:42:52

02.生成式人工智能和大型语言模型简介

生成式人工智能和大型语言模型简介 生成式人工智能是一种能够生成文本、图像及其他类型内容的人工智能技术。它的神奇之处在于&#xff0c;它让人工智能变得更加普及&#xff0c;任何人只需输入一个文本提示&#xff0c;即用自然语言写的一句话&#xff0c;就可以使用它。你不需…

作者头像 李华
网站建设 2026/2/7 4:08:53

03.探索和比较不同类型AI模型

探索和比较不同的LLM 在上一课中&#xff0c;我们已经了解了生成式人工智能如何改变技术格局&#xff0c;了解了大型语言模型&#xff08;LLM&#xff09;的工作原理&#xff0c;以及企业&#xff08;例如我们的初创公司&#xff09;如何将其应用于实际案例并实现增长&#xff…

作者头像 李华
网站建设 2026/2/13 8:40:04

HTML插槽与Shadow DOM:Web Components基础

HTML插槽与Shadow DOM&#xff1a;Web Components基础 引言 在Web开发领域&#xff0c;随着项目复杂度的不断提升&#xff0c;代码复用与组件化开发的需求愈发迫切。Web Components作为一项原生支持的技术&#xff0c;为开发者提供了创建可复用、封装性强的自定义组件的能力。其…

作者头像 李华