循环控制 #

一、break语句 #

1.1 基本用法 #

break语句用于跳出当前循环:

bash
#!/bin/bash

# 基本break使用
for i in {1..10}; do
    if [ $i -eq 5 ]; then
        echo "遇到5,跳出循环"
        break
    fi
    echo "数字: $i"
done

echo "循环结束"

1.2 跳出多层循环 #

bash
#!/bin/bash

# 跳出单层循环
for i in {1..3}; do
    for j in {1..3}; do
        if [ $j -eq 2 ]; then
            break  # 只跳出内层循环
        fi
        echo "i=$i, j=$j"
    done
done

echo "---"

# 跳出多层循环
for i in {1..3}; do
    for j in {1..3}; do
        if [ $i -eq 2 ] && [ $j -eq 2 ]; then
            break 2  # 跳出两层循环
        fi
        echo "i=$i, j=$j"
    done
done

echo "循环结束"

1.3 break在while中的应用 #

bash
#!/bin/bash

# 条件退出
count=0
while true; do
    ((count++))
    echo "计数: $count"
    
    if [ $count -ge 5 ]; then
        echo "达到上限,退出"
        break
    fi
    
    sleep 1
done

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

二、continue语句 #

2.1 基本用法 #

continue语句用于跳过本次迭代,继续下一次循环:

bash
#!/bin/bash

# 基本continue使用
for i in {1..10}; do
    if [ $((i % 2)) -eq 0 ]; then
        continue  # 跳过偶数
    fi
    echo "奇数: $i"
done

# 跳过特定条件
for file in *.txt; do
    if [ ! -r "$file" ]; then
        echo "跳过不可读文件: $file"
        continue
    fi
    
    echo "处理文件: $file"
    # 处理逻辑
done

2.2 continue在while中的应用 #

bash
#!/bin/bash

# 跳过特定行
while IFS= read -r line; do
    # 跳过空行
    if [ -z "$line" ]; then
        continue
    fi
    
    # 跳过注释行
    if [[ "$line" =~ ^# ]]; then
        continue
    fi
    
    echo "处理: $line"
done < file.txt

# 跳过无效输入
while true; do
    read -p "输入数字 (0退出): " num
    
    # 退出条件
    if [ "$num" = "0" ]; then
        break
    fi
    
    # 验证输入
    if ! [[ "$num" =~ ^[0-9]+$ ]]; then
        echo "无效输入,请输入数字"
        continue
    fi
    
    echo "输入的数字: $num"
done

2.3 跳过多层循环 #

bash
#!/bin/bash

# continue跳过外层循环
for i in {1..3}; do
    for j in {1..3}; do
        if [ $j -eq 2 ]; then
            continue 2  # 跳到外层循环的下一次迭代
        fi
        echo "i=$i, j=$j"
    done
done

三、循环控制实战 #

3.1 查找第一个匹配项 #

bash
#!/bin/bash

# 查找第一个包含关键字的文件
find_first_match() {
    local keyword="$1"
    local dir="${2:-.}"
    
    for file in "$dir"/*; do
        if [ -f "$file" ] && grep -q "$keyword" "$file"; then
            echo "找到匹配文件: $file"
            break
        fi
    done
}

find_first_match "error" "/var/log"

# 查找第一个可用的服务
find_available_service() {
    local services=("nginx" "apache2" "httpd")
    
    for service in "${services[@]}"; do
        if systemctl is-active --quiet "$service" 2>/dev/null; then
            echo "可用服务: $service"
            break
        fi
    done
}

3.2 数据验证 #

bash
#!/bin/bash

# 验证所有文件是否可读
validate_files() {
    local all_ok=true
    
    for file in "$@"; do
        if [ ! -f "$file" ]; then
            echo "错误: 文件不存在: $file"
            all_ok=false
            continue
        fi
        
        if [ ! -r "$file" ]; then
            echo "错误: 文件不可读: $file"
            all_ok=false
            continue
        fi
        
        echo "验证通过: $file"
    done
    
    $all_ok
}

# 验证配置
validate_config() {
    local config_file="$1"
    
    while IFS='=' read -r key value; do
        # 跳过注释和空行
        [[ "$key" =~ ^#.*$ ]] && continue
        [[ -z "$key" ]] && continue
        
        # 验证必需配置
        if [ -z "$value" ]; then
            echo "错误: $key 未设置值"
            break
        fi
        
        echo "$key = $value"
    done < "$config_file"
}

3.3 批量处理 #

bash
#!/bin/bash

# 批量处理文件,跳过错误
process_files() {
    local success=0
    local failed=0
    
    for file in "$@"; do
        # 检查文件
        if [ ! -f "$file" ]; then
            echo "跳过: $file (不存在)"
            ((failed++))
            continue
        fi
        
        # 处理文件
        if process_one "$file"; then
            echo "成功: $file"
            ((success++))
        else
            echo "失败: $file"
            ((failed++))
        fi
    done
    
    echo "处理完成: 成功 $success, 失败 $failed"
}

# 带重试的处理
process_with_retry() {
    local file="$1"
    local max_retries=3
    local retry=0
    
    while [ $retry -lt $max_retries ]; do
        if process_one "$file"; then
            return 0
        fi
        
        ((retry++))
        echo "重试 $retry/$max_retries: $file"
        sleep 1
    done
    
    return 1
}

3.4 交互式菜单 #

bash
#!/bin/bash

show_menu() {
    echo "========================"
    echo "    主菜单"
    echo "========================"
    echo "1. 选项一"
    echo "2. 选项二"
    echo "3. 选项三"
    echo "4. 返回上级"
    echo "5. 退出"
    echo "========================"
}

submenu() {
    while true; do
        echo "=== 子菜单 ==="
        echo "1. 子选项一"
        echo "2. 子选项二"
        echo "3. 返回"
        read -p "选择: " sub_choice
        
        case $sub_choice in
            1) echo "执行子选项一" ;;
            2) echo "执行子选项二" ;;
            3) break ;;  # 返回主菜单
            *) echo "无效选择" ;;
        esac
    done
}

# 主循环
while true; do
    show_menu
    read -p "请选择: " choice
    
    case $choice in
        1)
            echo "执行选项一"
            ;;
        2)
            echo "执行选项二"
            ;;
        3)
            submenu  # 进入子菜单
            ;;
        4)
            echo "返回上级"
            continue  # 继续主循环
            ;;
        5)
            echo "退出系统"
            break  # 退出主循环
            ;;
        *)
            echo "无效选择,请重新输入"
            continue
            ;;
    esac
    
    read -p "按回车继续..."
done

四、循环控制最佳实践 #

4.1 使用函数简化循环 #

bash
#!/bin/bash

# 不推荐:复杂的循环逻辑
for file in *.txt; do
    if [ -f "$file" ]; then
        if [ -r "$file" ]; then
            if [ -s "$file" ]; then
                # 处理逻辑
                echo "处理: $file"
            fi
        fi
    fi
done

# 推荐:使用函数封装
is_valid_file() {
    local file="$1"
    [ -f "$file" ] && [ -r "$file" ] && [ -s "$file" ]
}

for file in *.txt; do
    is_valid_file "$file" || continue
    echo "处理: $file"
done

4.2 避免深层嵌套 #

bash
#!/bin/bash

# 不推荐:深层嵌套
for item in "$@"; do
    if [ -n "$item" ]; then
        if [ -f "$item" ]; then
            if [ -r "$item" ]; then
                echo "处理: $item"
            else
                echo "不可读: $item"
            fi
        else
            echo "不是文件: $item"
        fi
    else
        echo "空参数"
    fi
done

# 推荐:提前退出
for item in "$@"; do
    [ -z "$item" ] && { echo "空参数"; continue; }
    [ ! -f "$item" ] && { echo "不是文件: $item"; continue; }
    [ ! -r "$item" ] && { echo "不可读: $item"; continue; }
    
    echo "处理: $item"
done

4.3 使用标签(Bash 4.0+) #

bash
#!/bin/bash

# 使用标签跳出多层循环
outer:
for i in {1..3}; do
    for j in {1..3}; do
        for k in {1..3}; do
            if [ $i -eq 2 ] && [ $j -eq 2 ]; then
                break outer
            fi
            echo "i=$i, j=$j, k=$k"
        done
    done
done

echo "跳出所有循环"

五、循环控制速查 #

5.1 控制语句 #

语句 说明 示例
break 跳出循环 break
break n 跳出n层循环 break 2
continue 跳过本次迭代 continue
continue n 跳过n层循环的本次迭代 continue 2
exit 退出脚本 exit 0
return 退出函数 return 0

5.2 使用场景 #

场景 推荐语句
找到目标后退出 break
跳过无效数据 continue
遇到错误退出 exit
函数返回 return

六、总结 #

6.1 循环控制要点 #

要点 说明
break 完全跳出循环
continue 跳过本次迭代
break n 跳出n层循环
continue n 跳过n层循环的本次迭代
使用场景 条件退出、跳过无效数据

6.2 下一步 #

你已经掌握了循环控制,接下来让我们学习 函数基础,了解Shell函数的定义和使用!

最后更新:2026-03-27