shell for 循环 数组(千字长文)
💡一则或许对你有用的小广告
欢迎加入小哈的星球 ,你将获得:专属的项目实战 / 1v1 提问 / Java 学习路线 / 学习打卡 / 每月赠书 / 社群讨论
- 新项目:《从零手撸:仿小红书(微服务架构)》 正在持续爆肝中,基于
Spring Cloud Alibaba + Spring Boot 3.x + JDK 17...
,点击查看项目介绍 ;- 《从零手撸:前后端分离博客项目(全栈开发)》 2 期已完结,演示链接: http://116.62.199.48/ ;
截止目前, 星球 内专栏累计输出 82w+ 字,讲解图 3441+ 张,还在持续爆肝中.. 后续还会上新更多项目,目标是将 Java 领域典型的项目都整一波,如秒杀系统, 在线商城, IM 即时通讯,权限管理,Spring Cloud Alibaba 微服务等等,已有 2900+ 小伙伴加入学习 ,欢迎点击围观
在 Shell 脚本编程中,for 循环和数组是两个核心工具。它们的结合不仅能够高效处理批量数据,还能显著提升自动化脚本的灵活性。无论是遍历文件列表、处理日志数据,还是执行复杂操作,shell for 循环数组的组合都能帮助开发者快速实现目标。本文将从基础概念入手,结合实例逐步讲解如何掌握这一技能,并深入探讨其在实际场景中的应用。
一、Shell 数组:数据存储的“购物车”
1.1 数组是什么?
数组可以理解为一个“购物车”,能够一次性存放多个数据项。例如,存储多个文件名、用户列表或数字序列。在 Shell 中,数组的定义和操作相对简单,但需要注意其特性与语法细节。
1.1.1 数组的定义方式
Shell 数组支持多种定义方法,以下是常见的两种:
fruits=("apple" "banana" "cherry")
vegetables[0]="carrot"
vegetables[1]="broccoli"
vegetables[2]="spinach"
注意:在 Shell 中,数组索引默认从
0
开始,且无需预先声明数组长度。
1.1.2 访问数组元素
通过索引访问数组元素:
echo ${fruits[0]} # 输出 "apple"
echo ${vegetables[2]} # 输出 "spinach"
若需获取数组所有元素,使用 @
或 *
:
echo ${fruits[@]} # 输出 "apple banana cherry"(以空格分隔)
1.1.3 数组长度
通过 $#
符号获取数组长度:
echo ${#fruits[@]} # 输出 "3"
二、For 循环:逐个处理数据的“传送带”
2.1 For 循环的语法结构
For 循环是 Shell 中最常用的迭代结构,语法如下:
for variable in item1 item2 item3 ...
do
# 循环体
done
例如,遍历数字序列 1 2 3 4 5
:
for num in 1 2 3 4 5
do
echo "当前数字是 $num"
done
2.2 使用序列生成器简化代码
Shell 支持通过 {start..end}
生成数字序列:
for num in {1..5}
do
echo "当前数字是 $num"
done
甚至可以指定步长:
for num in {10..1..2}
do
echo $num # 输出 10 8 6 4 2
done
三、数组与 For 循环的结合:批量处理的“组合拳”
3.1 基础用法:遍历数组元素
通过 for
循环与数组结合,可以逐个处理数组中的元素。例如,打印所有水果名称:
fruits=("apple" "banana" "cherry")
for fruit in "${fruits[@]}"
do
echo "水果名称:$fruit"
done
关键点:使用双引号包裹
${fruits[@]}
,避免因元素包含空格导致误拆分。
3.2 索引遍历:通过位置访问元素
若需同时获取元素索引和值,可通过 seq
或 for 循环
结合索引实现:
for index in ${!fruits[@]}
do
echo "索引 $index 对应的水果是:${fruits[$index]}"
done
输出结果:
索引 0 对应的水果是:apple
索引 1 对应的水果是:banana
索引 2 对应的水果是:cherry
3.3 实际案例:批量处理文件
假设需要遍历当前目录下的所有 .txt
文件并统计行数:
files=(*.txt)
for file in "${files[@]}"
do
line_count=$(wc -l < "$file")
echo "$file 包含 $line_count 行"
done
四、进阶技巧:让循环更灵活的“工具箱”
4.1 多维数组:嵌套结构的处理
Shell 不直接支持多维数组,但可通过字符串分割模拟:
matrix="1,2,3;4,5,6;7,8,9"
for row in ${matrix//;/ }
do
# 遍历列
for num in ${row//,/ }
do
echo -n "$num "
done
echo ""
done
输出结果:
1 2 3
4 5 6
7 8 9
4.2 嵌套循环:组合逻辑的“齿轮联动”
嵌套循环适用于需要双重遍历的场景,例如生成坐标点:
for x in {1..2}
do
for y in {A..B}
do
echo "坐标 ($x, $y)"
done
done
输出结果:
坐标 (1, A)
坐标 (1, B)
坐标 (2, A)
坐标 (2, B)
4.3 变量引用与安全性
在循环中处理动态数据时,需注意变量引用的安全性。例如,处理包含空格的文件名:
files=("file 1.txt" "file2.txt")
for file in ${files[@]}
do
echo "文件名:$file"
done
for file in "${files[@]}"
do
echo "文件名:$file"
done
五、常见问题与解决方案
5.1 数组索引越界
尝试访问超出范围的索引时,Shell 默认返回空值。可通过判断长度避免错误:
if [ $index -lt ${#fruits[@]} ]
then
echo "元素存在:${fruits[$index]}"
else
echo "索引越界"
fi
5.2 动态修改数组
在循环中动态添加或删除元素可能导致意外结果。建议在循环外操作数组:
for item in "${array[@]}"
do
array+=("new_item")
...
done
六、实战案例:日志分析脚本
6.1 需求:统计访问日志中的 IP 地址
假设日志文件 access.log
内容如下:
192.168.1.10 - [10/May/2023] "GET /home"
192.168.1.11 - [10/May/2023] "POST /login"
192.168.1.10 - [10/May/2023] "GET /about"
编写脚本统计每个 IP 的访问次数:
declare -A ip_counts # 声明关联数组
while read -r line
do
ip=$(echo $line | cut -d ' ' -f1)
((ip_counts[$ip]++))
done < access.log
for ip in "${!ip_counts[@]}"
do
echo "$ip 访问了 ${ip_counts[$ip]} 次"
done
输出结果:
192.168.1.10 访问了 2 次
192.168.1.11 访问了 1 次
七、结论
掌握 shell for 循环数组 的组合技巧,能够显著提升脚本的效率和可读性。从基础的数组定义到复杂的数据处理,通过实际案例的演练,开发者可以逐步构建出灵活且健壮的自动化解决方案。建议读者通过以下步骤深入学习:
- 从简单的数组遍历开始,逐步尝试嵌套循环和多维数据处理;
- 结合实际需求,例如文件管理、日志分析,设计具体脚本;
- 参考官方文档(如
man bash
)了解高级特性,如关联数组、数组切片等。
通过持续实践,shell for 循环数组将成为你自动化工作流中的得力工具,帮助你轻松应对各类批量处理任务。