循环是编程语言的核心概念之一,当你想重复执行一系列命令直到某个条件达成时,它们就派上用场了。在像 Bash 这样的脚本语言里,循环可帮我们自动化那些乏味的任务,省去了重复写同样代码的麻烦。
0 秒 of 15 秒 音量 0%
这个广告将在 15 秒后结束
Bash 脚本中有三种基本的循环结构:for
循环、while
循环 和 until
循环。
在这篇文章中,我们将带你了解 Bash 中 for
循环的基础知识,并教你如何使用 break
和 continue
语句来改变循环的流程。
标准 Bash for
循环
for
循环会遍历一个项目列表,并对每个项目执行给定的一组命令。它的格式如下:
for item in [LIST]
do
[COMMANDS]
done
这里的列表可以是一串由空格分隔的字符串、一组数字范围、命令输出、数组,或者是从命令行传入的参数等。
遍历字符串
下面的例子展示了一个遍历字符串列表的循环。每次循环都会处理列表中的一个元素,变量 element
会保存当前正在处理的元素。
for element in Hydrogen Helium Lithium Beryllium
do
echo "元素: $element"
done
输出结果会是这样的:
元素: Hydrogen
元素: Helium
元素: Lithium
元素: Beryllium
遍历数字范围
你可以使用序列表达式来指定一个数字或字符的范围,只需定义起始点和终点即可。格式如下:
{START..END}
这里有一个例子,它会遍历从 0 到 3 的所有数字:
for i in {0..3}
do
echo "数字: $i"
done
输出结果为:
数字: 0
数字: 1
数字: 2
数字: 3
从 Bash 4 开始,你还可以在使用范围时指定步长。格式如下:
{START..END..INCREMENT}
比如,以 5 为步长递增的示例如下:
for i in {0..20..5}
do
echo "数字: $i"
done
输出结果为:
数字: 0
数字: 5
数字: 10
数字: 15
数字: 20
遍历数组元素
你也可以用 for
循环来遍历数组中的元素。下面的例子定义了一个名为 BOOKS
的数组,并遍历其每一个元素。
BOOKS=('In Search of Lost Time' 'Don Quixote' 'Ulysses' 'The Great Gatsby')
for book in "${BOOKS[@]}"; do
echo "书名: $book"
done
输出结果为:
书名: In Search of Lost Time
书名: Don Quixote
书名: Ulysses
书名: The Great Gatsby
C 风格的 Bash for
循环
C 风格的 for
循环语法如下:
for ((INITIALIZATION; TEST; STEP))
do
[COMMANDS]
done
INITIALIZATION
部分仅在循环开始时执行一次。然后评估 TEST
部分;如果结果为假,则终止循环;如果 TEST
结果为真,则执行 for
循环体内的命令并更新 STEP
部分。
下面的例子中,循环从 i = 0
开始,每轮迭代前检查 i ≤ 1000
是否成立。如果是,打印 i
的当前值并将 i
增加 1 (i++
);否则,循环终止。
for ((i = 0 ; i <= 1000 ; i++)); do
echo "计数器: $i"
done
循环将迭代 1001 次,输出如下:
计数器: 0
计数器: 1
计数器: 2
...
计数器: 998
计数器: 999
计数器: 1000
循环嵌套
嵌套循环就是一个循环内部包含另一个循环。你可以任意多次地嵌套任何类型的循环。
在一个嵌套的 for
循环中,内层循环会在外层循环的每一次迭代中完成自己的全部迭代。这意味着每当外层循环执行一次,内层循环就会执行完所有的迭代,直到外层循环完成它的周期。
下面是一个示例代码,它逐个将三个文件复制到三台服务器上。
for f in file_{1..3}; do
for j in server_{1..3}; do
echo "正在复制文件 $f 到服务器 $j";
# 复制文件的命令
done;
done
输出结果为:
正在复制文件 file_1 到服务器 server_1
正在复制文件 file_1 到服务器 server_2
正在复制文件 file_1 到服务器 server_3
正在复制文件 file_2 到服务器 server_1
正在复制文件 file_2 到服务器 server_2
正在复制文件 file_2 到服务器 server_3
正在复制文件 file_3 到服务器 server_1
正在复制文件 file_3 到服务器 server_2
正在复制文件 file_3 到服务器 server_3
break
和 continue
语句
break
和 continue
语句可用于控制 for
循环的执行。
break
语句
break
语句会终止当前的循环,并将程序控制权传递给紧随其后的语句。通常用于当特定条件满足时提前结束循环。
在下面的例子中,我们使用 if
语句来检测当前迭代的元素是否等于 ‘Lithium’,一旦相等就终止循环的执行。
for element in Hydrogen Helium Lithium Beryllium; do
if [[ "$element" == 'Lithium' ]]; then
break
fi
echo "元素: $element"
done
echo '搞定了!'
输出结果为:
元素: Hydrogen
元素: Helium
搞定了!
continue
语句
continue
语句会退出当前循环的迭代,并将程序控制权传递给下一个迭代。
下面的例子中,我们在遍历一组数字时,如果当前迭代的元素等于 ‘2’,continue
语句会让执行返回到循环的开头,继续进行下一次迭代。
for i in {1..5}; do
if [[ "$i" == '2' ]]; then
continue
fi
echo "数字: $i"
done
输出结果为:
数字: 1
数字: 3
数字: 4
数字: 5
Bash for
循环实例
将文件名中的空格替换为下划线
下面的例子展示了如何将当前目录下所有带有空格的文件名中的空格替换为下划线:
for file in *\ *; do
mv "$file" "${file// /_}"
done
让我们一行一行地拆解这段代码:
- 第一行创建了一个
for
循环,遍历所有名字中含有空格的文件。表达式*\ *
生成了这个列表。 - 第二行针对列表中的每个项目,将文件移动到一个新的位置,把空格替换成下划线 (
_
)。${file// /_}
使用了 shell 参数扩展 来替换参数中的模式。 done
表示循环段落的结束。
更改文件扩展名
下面的例子展示了如何使用 Bash for
循环将当前目录下所有以 .jpeg 结尾的文件重命名为 .jpg。
for file in *.jpeg; do
mv -- "$file" "${file%.jpeg}.jpg"
done
分析一下这段代码:
- 第一行创建了一个
for
循环,遍历所有以 ‘.jpeg’ 结尾的文件。 - 第二行针对列表中的每个项目,将文件移动到新的位置,把 ‘.jpeg’ 替换为 ‘.jpg’。
${file%.jpeg}
用来移除文件名中的 ‘.jpeg’ 部分,利用了 shell 参数扩展 done
表示循环段落的结束。
总结
Bash 的 for
循环用来重复执行一组命令,次数固定。希望这些内容能让你更好地掌握 for
循环的用法,让脚本编写变得更加轻松有趣!