人人都会AI编程

数组定义、访问、遍历

更新时间:2026-07-12

在 Shell 脚本(特别是 Bash)中,数组是一种非常实用的数据结构,用于批量处理文件名、参数列表或远程服务器地址。掌握它的定义、访问和遍历,可以让你的脚本更简洁、更强大。


1. 数组定义

Bash 支持普通索引数组(数字下标)和关联数组(字符串下标,需 Bash 4+)。定义数组时,用一对圆括号将元素括起来,元素之间用空格分隔。

# 定义普通索引数组(下标从 0 开始)
servers=(web01 web02 db01 cache01)

# 也可以用逐步赋值的方式
files[0]="/etc/hosts"
files[1]="/etc/resolv.conf"
files[2]="/etc/fstab"

# 使用通配符或命令输出直接生成数组
log_files=(/var/log/*.log)
users=($(awk -F: '{print $1}' /etc/passwd))

关联数组需要先 declare -A 声明,用来建立键值对映射:

declare -A ports
ports=([http]=80 [https]=443 [ssh]=22)
# 或者逐个赋值
ports[ftp]=21

2. 访问数组元素

访问数组元素必须使用 ${} 语法,并且用下标引用。

| 操作 | 语法 | 示例结果(以上方 servers 为例) |
|------|------|----------------------------------|
| 获取单个元素 | ${数组名[下标]} | ${servers[0]}web01 |
| 获取所有元素 | ${数组名[@]}${数组名[*]} | web01 web02 db01 cache01 |
| 获取元素个数 | ${#数组名[@]} | 4 |
| 获取所有索引(键) | ${!数组名[@]} | 0 1 2 3 |
| 获取某元素长度 | ${#数组名[下标]} | ${#servers[0]}5 |
| 截取部分元素 | ${数组名[@]:起始:数量} | ${servers[@]:1:2}web02 db01 |

注意@ 在双引号内有重要区别。"${servers[@]}" 会将每个元素当作独立的单词,而 "${servers[]}" 会把所有元素合并成一个字符串(以 IFS 第一个字符连接)。循环处理时务必用 "${数组[@]}" 避免单词拆分问题。

关联数组的访问使用键名:

echo "${ports[http]}"   # 输出 80
echo "${!ports[@]}"     # 输出所有键:http https ssh ftp

3. 遍历数组

遍历数组常见有两种方式:按元素直接遍历,或按索引遍历。

(1)直接遍历元素(推荐)

for host in "${servers[@]}"; do
    echo "正在检查 ${host} ..."
    ping -c 2 "${host}"
done

这种方式下变量 host 依次取到每个数组元素的值,书写简单,且能正确处理元素中包含的空格。

(2)通过索引遍历
当你还需要用到下标,或者遍历关联数组时:

# 索引数组
for i in "${!servers[@]}"; do
    echo "第 ${i} 台服务器: ${servers[$i]}"
done

# 关联数组
for service in "${!ports[@]}"; do
    echo "${service} 监听端口: ${ports[$service]}"
done

典型实用场景:批量文件操作

config_files=(/etc/nginx/nginx.conf /etc/ssh/sshd_config /etc/hosts)
for conf in "${config_files[@]}"; do
    if [[ -f "$conf" ]]; then
        echo "备份 $conf 到 /backup"
        cp "$conf" /backup/
    fi
done

4. 常用技巧备忘

  • 追加元素servers+=(new_host)
  • 删除元素unset servers[1](注意下标会不连续)
  • 切片赋值daily_backups=("${all_backups[@]:0:7}")
  • 从字符串生成数组:利用 IFS 自定义分隔符
  IFS=',' read -ra fields <<< "name,age,city"
  echo "${fields[1]}"   # age
  

数组让 Shell 脚本有能力处理列表数据,而无需临时写入文件。只要注意用双引号包裹 ${数组[@]},就能避免绝大多数由空格和换行引起的意外,让你的脚本既健壮又清晰。