while循环 #

一、while循环基础 #

1.1 基本语法 #

bash
while [ 条件 ]; do
    命令
done

1.2 简单示例 #

bash
#!/bin/bash

# 基本计数
count=1
while [ $count -le 5 ]; do
    echo "计数: $count"
    ((count++))
done

# 使用 (( ))
num=0
while (( num < 5 )); do
    echo "数字: $num"
    ((num++))
done

二、while循环应用 #

2.1 读取文件 #

bash
#!/bin/bash

# 逐行读取文件
while IFS= read -r line; do
    echo "行: $line"
done < file.txt

# 读取带分隔符的文件
while IFS=',' read -r name age city; do
    echo "姓名: $name, 年龄: $age, 城市: $city"
done < data.csv

# 从命令输出读取
while read -r line; do
    echo "处理: $line"
done < <(ls -la)

2.2 用户输入处理 #

bash
#!/bin/bash

# 持续获取输入直到退出
while true; do
    read -p "请输入命令 (q退出): " cmd
    
    case "$cmd" in
        q|Q|quit|exit)
            echo "再见!"
            break
            ;;
        *)
            echo "执行: $cmd"
            ;;
    esac
done

# 验证输入
while true; do
    read -p "请输入数字: " num
    
    if [[ "$num" =~ ^[0-9]+$ ]]; then
        echo "输入正确: $num"
        break
    else
        echo "请输入有效数字"
    fi
done

2.3 等待条件满足 #

bash
#!/bin/bash

# 等待服务启动
echo "等待服务启动..."
while ! systemctl is-active --quiet nginx; do
    echo "等待中..."
    sleep 1
done
echo "服务已启动"

# 等待文件创建
file="/tmp/signal"
while [ ! -f "$file" ]; do
    echo "等待文件 $file ..."
    sleep 1
done
echo "文件已创建"

# 等待进程结束
pid=12345
while kill -0 $pid 2>/dev/null; do
    echo "进程 $pid 仍在运行..."
    sleep 1
done
echo "进程已结束"

2.4 倒计时 #

bash
#!/bin/bash

# 简单倒计时
count=10
while [ $count -gt 0 ]; do
    echo "倒计时: $count"
    sleep 1
    ((count--))
done
echo "时间到!"

# 格式化倒计时
seconds=90
while [ $seconds -gt 0 ]; do
    mins=$((seconds / 60))
    secs=$((seconds % 60))
    printf "\r剩余时间: %02d:%02d" $mins $secs
    sleep 1
    ((seconds--))
done
echo ""
echo "完成!"

三、无限循环 #

3.1 创建无限循环 #

bash
#!/bin/bash

# 方式一:while true
while true; do
    echo "运行中..."
    sleep 1
done

# 方式二:while :
while :; do
    echo "运行中..."
    sleep 1
done

# 方式三:while [ 1 ]
while [ 1 ]; do
    echo "运行中..."
    sleep 1
done

3.2 守护进程示例 #

bash
#!/bin/bash

# 简单守护进程
daemon() {
    local pidfile="/tmp/mydaemon.pid"
    
    # 检查是否已运行
    if [ -f "$pidfile" ]; then
        pid=$(cat "$pidfile")
        if kill -0 "$pid" 2>/dev/null; then
            echo "守护进程已在运行 (PID: $pid)"
            return 1
        fi
    fi
    
    # 写入PID
    echo $$ > "$pidfile"
    
    # 主循环
    while true; do
        # 执行任务
        echo "$(date): 执行任务..."
        
        # 检查是否需要退出
        if [ -f "/tmp/stop_daemon" ]; then
            rm -f "/tmp/stop_daemon"
            break
        fi
        
        sleep 60
    done
    
    # 清理
    rm -f "$pidfile"
    echo "守护进程退出"
}

daemon

3.3 监控脚本 #

bash
#!/bin/bash

# 系统监控
monitor() {
    local interval=5
    
    while true; do
        clear
        echo "=== 系统监控 ==="
        echo "时间: $(date)"
        echo ""
        
        # CPU使用率
        cpu_usage=$(top -bn1 | grep "Cpu(s)" | awk '{print $2}')
        echo "CPU使用率: ${cpu_usage}%"
        
        # 内存使用
        mem_info=$(free -m | awk 'NR==2{printf "%.1f%%", $3*100/$2}')
        echo "内存使用: $mem_info"
        
        # 磁盘使用
        disk_info=$(df -h / | awk 'NR==2{print $5}')
        echo "磁盘使用: $disk_info"
        
        # 网络连接数
        conn_count=$(netstat -an | grep ESTABLISHED | wc -l)
        echo "网络连接: $conn_count"
        
        sleep "$interval"
    done
}

monitor

四、while循环高级用法 #

4.1 多条件循环 #

bash
#!/bin/bash

# 使用 (( )) 进行多条件判断
a=0
b=10
while (( a < 5 && b > 5 )); do
    echo "a=$a, b=$b"
    ((a++))
    ((b--))
done

# 使用 [[ ]] 进行多条件判断
file_count=0
max_files=10
while [[ $file_count -lt $max_files && -f "file_${file_count}.txt" ]]; do
    echo "处理文件: file_${file_count}.txt"
    ((file_count++))
done

4.2 嵌套while循环 #

bash
#!/bin/bash

# 打印乘法表
i=1
while [ $i -le 9 ]; do
    j=1
    while [ $j -le $i ]; do
        printf "%d*%d=%-4d" $j $i $((j*i))
        ((j++))
    done
    echo ""
    ((i++))
done

# 读取多个文件
while IFS= read -r file1; do
    while IFS= read -r file2; do
        echo "比较: $file1 vs $file2"
    done < file2.txt
done < file1.txt

4.3 读取管道输入 #

bash
#!/bin/bash

# 从管道读取
echo -e "line1\nline2\nline3" | while read -r line; do
    echo "处理: $line"
done

# 注意:管道中的while在子Shell中执行
count=0
echo -e "1\n2\n3" | while read -r num; do
    ((count++))
done
echo "计数: $count"  # 输出: 0(子Shell中的修改不生效)

# 解决方案:使用进程替换
count=0
while read -r num; do
    ((count++))
done < <(echo -e "1\n2\n3")
echo "计数: $count"  # 输出: 3

五、实战示例 #

5.1 菜单系统 #

bash
#!/bin/bash

show_menu() {
    clear
    echo "========================"
    echo "    系统管理菜单"
    echo "========================"
    echo "1. 查看系统信息"
    echo "2. 查看磁盘使用"
    echo "3. 查看内存使用"
    echo "4. 查看进程列表"
    echo "5. 退出"
    echo "========================"
}

while true; do
    show_menu
    read -p "请选择 [1-5]: " choice
    
    case $choice in
        1)
            echo "=== 系统信息 ==="
            uname -a
            ;;
        2)
            echo "=== 磁盘使用 ==="
            df -h
            ;;
        3)
            echo "=== 内存使用 ==="
            free -h
            ;;
        4)
            echo "=== 进程列表 ==="
            ps aux | head -20
            ;;
        5)
            echo "再见!"
            exit 0
            ;;
        *)
            echo "无效选择"
            ;;
    esac
    
    read -p "按回车继续..."
done

5.2 日志监控 #

bash
#!/bin/bash

log_file="/var/log/syslog"
pattern="ERROR"

echo "监控日志文件: $log_file"
echo "监控模式: $pattern"
echo ""

# 使用tail -f持续监控
tail -f "$log_file" | while read -r line; do
    if echo "$line" | grep -q "$pattern"; then
        echo "[ALERT] $line"
        # 可以添加告警逻辑
    fi
done

5.3 重试机制 #

bash
#!/bin/bash

# 带重试的命令执行
retry_command() {
    local max_attempts=$1
    local command="$2"
    local attempt=1
    
    while [ $attempt -le $max_attempts ]; do
        echo "尝试 $attempt/$max_attempts: $command"
        
        if eval "$command"; then
            echo "成功!"
            return 0
        fi
        
        echo "失败,等待重试..."
        sleep 2
        ((attempt++))
    done
    
    echo "达到最大重试次数"
    return 1
}

retry_command 3 "curl -f http://example.com/api"

5.4 进度监控 #

bash
#!/bin/bash

# 监控后台任务进度
monitor_progress() {
    local pid=$1
    local total=$2
    local current=0
    
    while kill -0 "$pid" 2>/dev/null; do
        # 模拟进度更新
        current=$((current + 1))
        if [ $current -gt $total ]; then
            current=$total
        fi
        
        percent=$((current * 100 / total))
        printf "\r进度: %d/%d (%d%%)" $current $total $percent
        sleep 0.5
    done
    
    echo ""
    echo "任务完成"
}

# 启动后台任务
sleep 10 &
pid=$!
monitor_progress $pid 20

六、while循环最佳实践 #

6.1 避免常见错误 #

bash
#!/bin/bash

# 错误:变量未加引号
file=""
while [ $file != "exit" ]; do  # 如果file为空会报错
    read -p "输入: " file
done

# 正确:变量加引号
file=""
while [ "$file" != "exit" ]; do
    read -p "输入: " file
done

# 错误:死循环
while true; do
    echo "运行中"
    # 忘记退出条件
done

# 正确:有退出条件
while true; do
    echo "运行中"
    read -p "继续? (y/n): " choice
    [ "$choice" = "n" ] && break
done

6.2 性能考虑 #

bash
#!/bin/bash

# 不推荐:频繁执行外部命令
while true; do
    date  # 每次都执行外部命令
    sleep 1
done

# 推荐:使用内置命令
while true; do
    printf '%(%Y-%m-%d %H:%M:%S)T\n' -1  # Bash内置
    sleep 1
done

# 推荐:减少循环次数
count=0
while [ $count -lt 1000 ]; do
    # 批量处理而不是逐个处理
    ((count++))
done

七、while循环速查 #

7.1 常用模式 #

模式 示例
条件循环 while [ $i -lt 10 ]; do … done
无限循环 while true; do … done
读取文件 while read line; do … done < file
读取输入 while read -p "输入: " var; do … done
等待条件 while [ ! -f file ]; do sleep 1; done

7.2 控制命令 #

命令 说明
break 跳出循环
continue 跳过本次迭代
exit 退出脚本
return 退出函数

八、总结 #

8.1 while循环要点 #

要点 说明
基本语法 while [ 条件 ]; do … done
无限循环 while true 或 while :
读取文件 while read line; do … done < file
条件等待 配合 sleep 使用
退出控制 使用 break 和 continue

8.2 下一步 #

你已经掌握了while循环,接下来让我们学习 until循环,了解直到型循环!

最后更新:2026-03-27