Shell 数组
《Shell 数组》
🧮 学习目标
- 掌握 Shell 中数组的定义、访问、遍历与操作方法。
- 理解索引数组和关联数组的区别,学会在不同场景下使用合适的数组类型。
- 学会在阿里云 Ubuntu ECS 上编写带数组的脚本,用于服务管理、日志分析、批量处理等实际场景。
- 掌握数组的常用操作:追加元素、删除元素、获取长度、切片、排序等。
- 能结合
for循环、条件判断等结构实现复杂逻辑。
🧠 核心重点(表格提炼)
| 内容 | 示例 | 说明 |
|---|---|---|
| 定义数组 | arr=(a b c) |
使用括号赋值 |
| 访问元素 | ${arr[0]} |
获取第一个元素 |
| 遍历数组 | for item in "${arr[@]}" |
推荐用法 |
| 获取长度 | ${#arr[@]} |
获取数组元素个数 |
| 追加元素 | arr+=(d) |
在末尾添加新元素 |
| 删除元素 | unset arr[1] |
可删除指定索引 |
| 切片操作 | ${arr[@]:1:2} |
获取从第1个开始的2个元素 |
| 关联数组 | declare -A map |
键值对存储(bash 4+) |
🔍 详细讲解
1. Shell 中有“数组”吗?🧐
是的!虽然 Shell 不是真正的编程语言,但它支持数组这种数据结构,能帮助我们更高效地处理多个变量或列表型数据。
📌 为什么重要?
- 处理多个文件、服务名、IP 地址时非常方便。
- 提高脚本灵活性,避免重复代码。
- 是构建自动化运维工具的基础。
📌 注意:
- Shell 的数组是字符串数组,不支持嵌套。
- 默认是索引数组(数字下标),也可使用关联数组(键值对)。
2. Shell 数组的基本操作 📝
✅ 1. 定义数组
services=("nginx" "mysql" "redis")
📌 也可以跨行写:
files=(
"/etc/passwd"
"/etc/group"
"/etc/shadow"
)
✅ 2. 访问数组元素
echo "${services[0]}" # 输出 nginx
echo "${services[1]}" # 输出 mysql
📌 注意:
- 数组索引从
0开始。 - 使用
{}包裹变量更安全。
✅ 3. 获取数组长度
echo "服务数量:${#services[@]}"
📌 输出:
服务数量:3
✅ 4. 遍历数组(推荐方式)
for service in "${services[@]}"; do
echo "正在检查服务:$service"
done
📌 说明:
"${services[@]}"是标准遍历方式,保留空格和特殊字符。- 不建议使用
$*,它会把整个数组当作一个字符串。
✅ 5. 追加元素到数组末尾
services+=("php-fpm")
📌 结果:
nginx mysql redis php-fpm
✅ 6. 删除数组中的某个元素
unset services[2] # 删除 redis
📌 注意:
- 删除后索引不会重新排列,可以使用
reindex或直接跳过空位。
✅ 7. 切片操作(获取子数组)
echo "${services[@]:1:2}"
📌 说明:
- 从索引
1开始取2个元素。 - 输出为:
mysql php-fpm
✅ 8. 替换元素内容
services[2]="mariadb"
📌 替换前: redis
📌 替换后: mariadb
3. 实战案例:ECS 上的数组应用 🛠️
场景一:批量重启服务并检查状态 ⚙️
你想编写一个脚本,自动重启一组服务,并检查它们的状态是否正常。
✅ 示例脚本 restart_services.sh:
#!/bin/bash
# 服务列表
services=("nginx" "mysql" "redis")
# 重启每个服务
for service in "${services[@]}"; do
echo "🔄 正在重启 $service..."
sudo systemctl restart "$service"
# 检查状态
if systemctl is-active --quiet "$service"; then
echo "✅ $service 重启成功"
else
echo "❌ $service 启动失败"
fi
done
📌 运行方式:
chmod +x restart_services.sh
./restart_services.sh
场景二:动态生成备份文件路径列表 🗂️
你想将多个目录打包备份,但目录名称可能包含空格或特殊字符。
✅ 示例脚本 backup_dirs.sh:
#!/bin/bash
dirs=("/home/ubuntu/logs" "/var/www/html" "/etc/nginx")
for dir in "${dirs[@]}"; do
if [ -d "$dir" ]; then
echo "📦 正在备份:$dir"
tar -czf "/home/ubuntu/backup_$(basename "$dir").tar.gz" "$dir"
else
echo "⚠️ 目录不存在:$dir"
fi
done
📌 优点:
- 支持含空格路径
- 动态生成备份文件名
场景三:使用关联数组保存配置信息 🎛️
你希望将一些配置参数以键值对形式保存,便于读取和修改。
✅ 示例脚本 config_loader.sh:
#!/bin/bash
# bash 4+ 才支持关联数组
declare -A config
config["db_host"]="localhost"
config["db_user"]="root"
config["db_pass"]="secret"
echo "数据库地址:${config["db_host"]}"
echo "用户名:${config["db_user"]}"
📌 输出:
数据库地址:localhost
用户名:root
📌 注意:
- 必须使用
bash执行,不能使用sh - 兼容性不如索引数组好
🧰 小贴士(进阶技巧)🔖
| 技巧 | 说明 |
|---|---|
mapfile / readarray |
快速将命令输出存入数组 |
sort / uniq |
对数组排序或去重 |
IFS=\n' |
设置分隔符按行分割 |
eval |
构建动态数组名(慎用) |
reindex |
手动重建数组索引 |
+=() |
批量追加多个元素 |
unset array[@] |
清空整个数组 |
📌 示例:读取文件每一行为数组元素
mapfile -t lines < <(cat /etc/passwd)
for line in "${lines[@]}"; do
echo "$line"
done
📌 注意事项与安全建议
| 项目 | 建议 |
|---|---|
| 使用双引号包裹所有变量引用 | 如 "$item" |
不要使用 eval 构造数组名 |
易引发安全问题 |
| 对输入数组做校验 | 防止空值或非法路径 |
| 删除元素后记得处理索引 | 避免出现“空洞” |
使用 mapfile 时注意内存占用 |
大文件可能导致性能下降 |
| 脚本中尽量使用局部数组 | 避免全局污染 |
🧩 附录:Shell 数组实战模板(推荐使用)
#!/bin/bash
# 脚本名称:check_files.sh
# 功能描述:检查多个文件是否存在
# 作者:Linux 专家
# 日期:2025-06-17
files=(
"/etc/passwd"
"/etc/group"
"/etc/nonexistent"
)
for file in "${files[@]}"; do
if [ -f "$file" ]; then
echo "✅ 文件存在:$file"
else
echo "❌ 文件不存在:$file"
fi
done
📌 运行效果:
✅ 文件存在:/etc/passwd
✅ 文件存在:/etc/group
❌ 文件不存在:/etc/nonexistent
🎯 总结一句话:
“Shell 数组就像一个智能收纳盒📦 —— 它能帮你整齐有序地管理多个变量,是你编写复杂脚本、提升自动化效率的关键武器!”
是否继续下一章?我将继续输出:
- 《Shell 条件判断与流程控制》⚙️
- 《Shell 函数与模块化编程》📦
- 《Shell 字符串操作与正则表达式》🔤
请告诉我你想深入的方向吧!🚀

浙公网安备 33010602011771号