Bash 零基础教程

Bash break 与 continue 语句

break 和 continue 语句为控制 Bash 脚本中的循环流程提供了强大的机制。它们允许你根据特定条件改变循环的常规执行轨迹,从而让你的脚本更加高效和灵活。

1. 理解 break 与 continue

breakcontinue 都是控制流语句,专门用在循环结构(如 forwhileuntil)内部,用来修改代码的执行方式。

1.1 break 语句

break 语句的作用是终止当前循环,并将程序的控制权转移到循环体之后的下一条语句。你可以把它想象成循环的“紧急出口”。一旦代码执行到 break,无论循环自身的条件是否仍然满足,循环都会立刻停止。

代码示例:

#!/bin/bash
for i in {1..10}
do
  if [ $i -gt 5 ]; then
    echo "在 i = $i 时中断循环 (Breaking the loop)"
    break  # 退出循环
  fi
  echo "i = $i"
done
echo "循环结束。"

在这个例子中,循环原本计划从 1 迭代到 10。然而,当 i 的值大于 5 时,break 语句被执行,循环提前终止。

输出结果:

i = 1
i = 2
i = 3
i = 4
i = 5
在 i = 6 时中断循环 (Breaking the loop)
循环结束。

原理解析: 脚本遍历数字 1 到 10。当 i 变成 6 时,条件 $i -gt 5 判断为真 (true)。随后 break 语句被触发,导致循环立刻终止。接着,脚本继续执行循环体外部的下一行代码,打印出“循环结束。”。

1.2 continue 语句

continue 语句的作用是跳过当前循环迭代的剩余部分,并直接进入下一次迭代。它本质上是直接跳到循环的下一个周期,而不执行当前周期内 continue 后面的那些命令。

代码示例:

#!/bin/bash
for i in {1..10}
do
  if [ $((i % 2)) -eq 0 ]; then
    continue  # 跳过偶数
  fi
  echo "i = $i"
done
echo "循环结束。"

在这个例子中,循环从 1 迭代到 10。当 i 是偶数时,continue 语句被执行,从而跳过了那次迭代中的 echo 命令。

输出结果:

i = 1
i = 3
i = 5
i = 7
i = 9
循环结束。

原理解析: 脚本遍历数字 1 到 10。对于每一个偶数,条件 $((i % 2)) -eq 0 为真。continue 语句执行后,跳过了当前迭代的剩余部分(即 echo 命令)。然后,脚本直接进入循环的下一个数字进行迭代。

2. 嵌套循环与标签

默认情况下,breakcontinue 都只影响它们所在的最内层循环。如果你想在内层循环中控制外层循环的行为,你需要使用标签 (labels)

2.1 带标签的 break

代码示例:

#!/bin/bash
outer_loop: for i in {1..3}
do
  echo "外层循环 i = $i"
  for j in {1..3}
  do
    echo "  内层循环 j = $j"
    if [ $i -eq 2 ] && [ $j -eq 2 ]; then
      echo "  中断外层循环!"
      break outer_loop # 直接跳出带有 outer_loop 标签的外层循环
    fi
  done
done
echo "循环结束。"

输出结果:

外层循环 i = 1
  内层循环 j = 1
  内层循环 j = 2
  内层循环 j = 3
外层循环 i = 2
  内层循环 j = 1
  内层循环 j = 2
  中断外层循环!
循环结束。

原理解析: 此示例演示了当满足内层循环中的某个条件时,如何直接跳出特定的(外层)循环。outer_loop: 标签标识了外层循环。随后的 break outer_loop 命令就会精准地跳出那个被标记的循环层级。

2.2 带标签的 continue

(注意:这种用法相对少见,但完全可行)

代码示例:

#!/bin/bash
outer_loop: for i in {1..5}
do
  for j in {1..3}
  do
    if [ $j -eq 2 ]; then
      continue outer_loop # 跳过外层循环的剩余部分,进入外层循环的下一次迭代
    fi
    echo "i=$i, j=$j"
  done
  echo "外层循环 i=$i 的迭代结束"
done

输出结果:

i=1, j=1
i=3, j=1
i=4, j=1
i=5, j=1

原理解析: continue outer_loop 语句跳过了当前外层循环迭代的剩余内容,并直接跳转到下一个 i 值。因此,“外层循环迭代结束”的消息以及 j=3 时的消息都被跳过了,因为外层循环被立即重新启动了。

3. 实用案例演示

3.1 跳过目录中的特定文件

假设你有一个包含多种文件的目录,你只想处理 .txt 文件,而跳过所有的 .log 日志文件。

#!/bin/bash
for file in *
do
  if [[ "$file" == *.log ]]; then
    echo "跳过日志文件: $file"
    continue # 跳过 .log 文件
  fi
  echo "正在处理文件: $file"
  # 在这里添加你的文件处理逻辑
done

在这个例子中,循环遍历当前目录下的所有文件。如果文件名以 .log 结尾,continue 语句就会跳过循环体的剩余部分,直接去检查下一个文件。

3.2 遇到特定错误时退出循环

假设你正在逐行读取一个文件的数据,如果遇到格式无效的行,你希望停止处理。

#!/bin/bash
while IFS= read -r line
do
  if [[ ! "$line" =~ ^[0-9]+,[A-Za-z]+$ ]]; then
    echo "遇到无效格式: $line"
    break # 如果格式无效,退出循环
  fi
  # 处理这行数据(前提是格式正确)
  echo "正在处理行: $line"
done < data.txt

这里,循环从 data.txt 中读取每一行。如果一行数据不符合预期的格式(例如:数字,后跟逗号,然后是字母),break 语句就会终止整个循环。

如果 data.txt 包含以下内容:

123,Valid
456,AnotherValid
Invalid Data
789,StillValid

那么输出结果将是:

正在处理行: 123,Valid
正在处理行: 456,AnotherValid
遇到无效格式: Invalid Data

3.3 使用 break 实现简单菜单

这个例子使用 break 退出代表菜单界面的无限 while 循环。

#!/bin/bash
while true; do
  echo "菜单:"
  echo "1. 选项 1"
  echo "2. 选项 2"
  echo "3. 退出"
  read -p "请输入你的选择: " choice
  case $choice in
    1)
      echo "正在执行选项 1"
      ;;
    2)
      echo "正在执行选项 2"
      ;;
    3)
      echo "正在退出..."
      break # 退出循环
      ;;
    *)
      echo "无效选择,请重试。"
      ;;
  esac
done
echo "程序运行结束。"

在这个例子中,while true 循环会无限运行,直到用户输入 '3'。此时 break 语句会被触发,从而终止循环。

3.4 使用 continue 过滤指定范围内的数字

此示例演示如何打印 1 到 20 之间的数字,但跳过 3 的倍数。

#!/bin/bash
for i in $(seq 1 20); do
  if [[ $((i % 3)) -eq 0 ]]; then
    continue # 跳过 3 的倍数
  fi
  echo "$i"
done

该脚本将输出 1 到 20 之间的数字,但会排除 3、6、9、12、15 和 18。