bash 关联数组需用 declare -a 显式声明,支持动态键名与自增统计,遍历用 "${!array[@]}",大文件推荐用 awk 原生关联数组提升性能。

关联数组必须先声明再使用
在 Bash 中,关联数组从 4.0 版本起支持,但不能像普通数组那样直接赋值。必须用 declare -A 显式声明,否则会当作普通数组处理,导致字符串索引被强制转为 0,所有值都堆到同一个位置。
正确写法示例:
- declare -A count
- count["error"]=0
- count["warning"]=0
也可以一步完成声明和初始化:declare -A count=([error]=0 [warning]=0 [info]=0)
用字段值作键实现自动累加统计
实际统计场景中,通常不需要预先定义所有键。只要声明了关联数组,就可以在循环中动态创建键并自增。常见做法是把日志行中的某字段(如状态码、IP、路径)作为键,每次出现就执行 array[$key]++。
例如统计 Nginx 日志中各 HTTP 状态码出现次数:
- declare -A status_count
- while read -r line; do
- code=$(echo "$line" | awk '{print $9}')
- ((status_count[$code]++))
- done
注意:用 ((...)) 可安全处理空值或未定义键,比 let 或 $((...)) 更稳妥。
遍历结果并格式化输出
统计完成后,用 for key in "${!array[@]}" 遍历所有键,再通过 ${array[$key]} 取对应值。这样能避免键名含空格或特殊字符时出错。
输出示例:
- for code in "${!status_count[@]}"; do
- printf "%-5s %d\n" "$code" "${status_count[$code]}"
- done | sort -k2nr
加上 sort -k2nr 可按计数值降序排列,便于快速定位高频项。
配合 awk 实现更高效的一体化统计
对大文件,纯 Shell 循环效率低。可交由 awk 完成,它原生支持关联数组且无需声明:
- awk '{count[$9]++} END {for (c in count) print c, count[c]}' access.log
- 若需排序,可追加:| sort -k2nr
这种写法省去 Shell 层解析开销,尤其适合 GB 级日志。关键点在于:awk 的 count[$9] 自动以第 9 字段为键建组,END 块统一输出,逻辑清晰、性能高。











