Pure Bash Bible 中的循环操作详解
前言
在 Bash 脚本编程中,循环结构是最基础也是最重要的控制结构之一。本文将深入探讨 Pure Bash Bible 中介绍的各种 Bash 循环技巧,帮助读者掌握高效、纯粹的 Bash 循环写法。
数字范围循环
固定范围循环
传统方式可能会使用 seq
命令生成数字序列,但 Pure Bash Bible 提供了更纯粹的 Bash 实现:
# 循环0到100(不支持变量)
for i in {0..100}; do
printf '%s\n' "$i"
done
这种写法利用了 Bash 的花括号扩展(Brace Expansion)特性,直接生成数字序列,避免了调用外部命令 seq
的开销。
变量范围循环
当循环范围需要由变量决定时,可以使用以下方式:
VAR=50
for ((i=0;i<=VAR;i++)); do
printf '%s\n' "$i"
done
这里使用了 Bash 的 C 风格 for 循环语法,(( ))
是算术运算的上下文环境,非常适合处理数字循环。
数组循环
简单数组遍历
Bash 数组遍历有多种方式,最直接的是:
arr=(apples oranges tomatoes)
for element in "${arr[@]}"; do
printf '%s\n' "$element"
done
"${arr[@]}"
展开为数组的所有元素,保留每个元素的原始内容(包括空格等特殊字符)。
带索引的数组遍历
有时我们需要同时获取数组元素和其索引:
arr=(apples oranges tomatoes)
# 方法一:使用 ${!arr[@]} 获取所有索引
for i in "${!arr[@]}"; do
printf '索引 %d: %s\n' "$i" "${arr[i]}"
done
# 方法二:C 风格循环
for ((i=0;i<${#arr[@]};i++)); do
printf '索引 %d: %s\n' "$i" "${arr[i]}"
done
第一种方法更简洁,第二种方法则提供了更精细的控制能力。
文件内容循环
逐行读取文件内容的推荐方法是:
while read -r line; do
printf '%s\n' "$line"
done < "file"
关键点:
-r
选项防止反斜杠转义- 输入重定向
<
比管道更高效 - 避免使用
for line in $(cat file)
,因为它会按空格分词而非按行
文件和目录循环
基本文件遍历
# 遍历当前目录所有文件
for file in *; do
printf '%s\n' "$file"
done
注意:永远不要使用 ls
命令的输出作为循环源,因为无法正确处理包含特殊字符(如空格、换行符)的文件名。
模式匹配
# 遍历家目录下所有 PNG 图片
for file in ~/Pictures/*.png; do
printf '%s\n' "$file"
done
目录遍历
# 只遍历目录(注意结尾的/)
for dir in ~/Downloads/*/; do
printf '%s\n' "$dir"
done
花括号扩展
# 同时遍历多个特定路径
for file in /path/to/parentdir/{file1,file2,subdir/file3}; do
printf '%s\n' "$file"
done
递归遍历
# 启用 globstar 选项支持 ** 递归匹配
shopt -s globstar
for file in ~/Pictures/**/*; do
printf '%s\n' "$file"
done
shopt -u globstar # 使用后关闭
**
会匹配所有文件和子目录,类似于 find
命令的功能,但更简洁。
最佳实践总结
- 避免使用外部命令(如
seq
,ls
)来实现循环,纯 Bash 方案通常更高效 - 处理文件名时总是使用引号包裹变量,防止分词和路径名扩展
- 对于数组和文件内容循环,优先考虑使用
"${array[@]}"
和while read
结构 - 需要递归遍历时,
globstar
选项比find
更简洁,但要注意启用和关闭的时机
掌握这些纯粹的 Bash 循环技巧,可以编写出更高效、更健壮的 shell 脚本。
创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考