跳至内容

Bash - 循环


**目标**:在本节中,您将学习如何

✔ 使用循环;

🏁 **linux**、**脚本**、**bash**、**循环**

**知识**:⭐ ⭐
**复杂度**:⭐ ⭐ ⭐

**阅读时间**:20 分钟


bash shell 允许使用**循环**。这些结构允许根据静态定义的值、动态地或有条件地**多次执行一个命令块**(从 0 到无穷大)。

  • while
  • until
  • for
  • select

无论使用哪个循环,要重复的命令都放在**`do` 和 `done` 关键字之间**。

while 条件循环结构

`while` / `do` / `done` 结构会评估 `while` 关键字后面的命令。

如果该命令为真(`$? = 0`),则执行 `do` 和 `done` 之间的命令。然后脚本返回开头重新评估该命令。

当评估的命令为假(`$? != 0`)时,shell 从 `done` 关键字后的第一个命令开始继续执行脚本。

`while` 条件循环结构的语法

while command
do
  command if $? = 0
done

使用 `while` 条件结构的示例

while [[ -e /etc/passwd ]]
do
  echo "The file exists"
done

如果评估的命令不发生变化,循环将无限循环,shell 将永远不会执行脚本后面的命令。这可能是故意的,也可能是一个错误。因此,您必须**非常小心地管理循环的命令,并找到一种退出循环的方法**。

要退出 `while` 循环,您必须确保被评估的命令不再为真,但这并非总是可能的。

有一些命令可以更改循环的行为

  • exit
  • break
  • continue

exit 命令

`exit` 命令结束脚本的执行。

`exit` 命令的语法

exit [n]

使用 `exit` 命令的示例

bash # to avoid being disconnected after the "exit 1
exit 1
echo $?
1

exit 命令立即结束脚本。可以通过提供参数(从 0255)来指定脚本的返回值。如果没有提供参数,脚本的最后一个命令的返回值将被传递给 $? 变量。

break / continue 命令

break 命令允许你通过转到 done 后的第一个命令来中断循环。

continue 命令允许你通过返回到 done 后的第一个命令来重新启动循环。

while [[ -d / ]]                                                   INT   17s do
  echo "Do you want to continue? (yes/no)"
  read ans
  [[ $ans = "yes" ]] && continue
  [[ $ans = "no" ]] && break
done

true / false 命令

true 命令始终返回 true,而 false 命令始终返回 false

true
echo $?
0
false
echo $?
1

用作循环的条件,它们允许执行无限循环或停用此循环。

示例

while true
do
  echo "Do you want to continue? (yes/no)"
  read ans
  [[ $ans = "yes" ]] && continue
  [[ $ans = "no" ]] && break
done

until 条件循环结构

until / do / done 结构评估放置在 until 后的命令。

如果此命令为假 ($? != 0),则执行放置在 dodone 之间的命令。然后脚本返回到开头以再次评估命令。

当评估的命令为真 ($? = 0) 时,shell 在 done 后的第一个命令处恢复脚本的执行。

until 条件循环结构的语法

until command
do
  command if $? != 0
done

until 条件结构的使用示例

until [[ -e test_until ]]
do
  echo "The file does not exist"
  touch test_until
done

select 替代选择结构

select / do / done 结构允许显示一个具有多个选项和输入请求的菜单。

列表中的每个项目都有一个编号的选择。当你输入一个选择时,选择的值被分配给放置在 select 后的变量(为此目的创建)。

然后它使用此值执行放置在 dodone 之间的命令。

  • PS3 变量包含输入选择的邀请;
  • REPLY 变量将返回选择的编号。

需要一个 break 命令来退出循环。

注意

select 结构非常适合小型和简单的菜单。要定制更完整的显示,必须在 while 循环中使用 echoread 命令。

select 条件循环结构的语法

PS3="Your choice:"
select variable in var1 var2 var3
do
  commands
done

select 条件结构的使用示例

PS3="Your choice: "
select choice in coffee tea chocolate
do
  echo "You have chosen the $REPLY: $choice"
done

如果运行此脚本,它会显示类似以下内容

1) Coffee
2) Tea
3) Chocolate
Your choice : 2
You have chosen choice 2: Tea
Your choice:

for 值列表上的循环结构

for / do / done 结构将列表的第一个元素分配给放置在 for 后的变量(此时创建)。然后它使用此值执行放置在 dodone 之间的命令。然后脚本返回到开头以将列表的下一个元素分配给工作变量。当最后一个元素被使用时,shell 在 done 后的第一个命令处恢复执行。

值列表 for 循环结构的语法

for variable in list
do
  commands
done

使用 for 条件结构的示例

for file in /home /etc/passwd /root/fic.txt
do
  file $file
done

任何产生值列表的命令都可以使用子执行放置在 in 之后。

  • IFS 变量包含 $' \t\n' 时,for 循环将把此命令结果的每个单词作为要循环的元素列表。
  • IFS 变量包含 $'\t\n'(即不包含空格)时,for 循环将获取此命令结果的每一行。

这可以是目录中的文件。在这种情况下,变量将取目录中存在的每个文件名的每个单词作为值。

for file in $(ls -d /tmp/*)
do
  echo $file
done

这可以是一个文件。在这种情况下,变量将取浏览的文件中包含的每个单词作为值,从开头到结尾。

cat my_file.txt
first line
second line
third line
for LINE in $(cat my_file.txt); do echo $LINE; done
first
line
second
line
third line
line

要逐行读取文件,必须修改 IFS 环境变量的值。

IFS=$'\t\n'
for LINE in $(cat my_file.txt); do echo $LINE; done
first line
second line
third line

作者:Antoine Le Morvan

贡献者:Steven Spencer,Ganna Zhyrnova