AWK 数组操作

《AWK 数组操作》


🎯 学习目标

  • 理解 AWK 中数组的基本语法与使用方式
  • 掌握如何利用数组进行统计、计数、去重等操作
  • 能够在日志分析、用户访问频率统计等实际场景中灵活运用数组
  • 理解关联数组(Associative Array)的特性,提升脚本效率
  • 熟悉不同 Linux 发行版(Ubuntu、CentOS、EulerOS)下的应用差异与注意事项

🔑 核心重点

概念 内容
数组类型 关联数组(键值对),索引可以是数字或字符串
定义方式 array[key] = value
遍历数组 使用 for (key in array) 遍历
常用操作 统计、计数、去重、合并、排序
典型应用场景 日志分析中的 IP 访问统计、请求路径统计、用户行为分析等

📚 详细讲解


一、AWK 数组简介

AWK 的数组是 关联数组(Associative Array),即你可以用任意字符串或数字作为下标。

示例1:简单定义与访问

awk 'BEGIN {
    arr["name"] = "Alice"
    arr["age"] = 30
    print arr["name"], arr["age"]
}'

输出:

Alice 30

✅ 特点:

  • 不需要提前声明数组大小
  • 键可以是字符串或数字
  • 支持动态扩展

二、实战案例:IP 地址访问频率统计

场景:统计 Nginx 日志中每个 IP 的访问次数

假设日志格式如下:

192.168.1.1 - - [10/May/2025:10:00:01 +0800] "GET /index.html HTTP/1.1" 200 612 "-" "Mozilla/5.0 ..."

我们提取 $1(IP地址)并统计访问次数:

awk '{ip[$1]++} END {for (i in ip) print i, ip[i]}' access.log

输出示例:

192.168.1.1 150
192.168.1.2 89

📌 解析:

  • ip[$1]++ 表示以 IP 为键,每次出现时计数加一
  • END{...} 遍历数组输出结果

三、实战案例:请求路径统计

场景:统计 Nginx 日志中各请求路径的访问量

awk '$7 != "" {path[$7]++} END {for (p in path) print p, path[p]}' access.log

说明:

  • $7 是请求路径字段
  • != "" 过滤空字段
  • 最终输出各路径访问次数

四、实战案例:去重处理(提取唯一值)

场景:提取所有不同的请求路径

awk '$7 != "" && !seen[$7]++ {print $7}' access.log

解释:

  • !seen[$7]++ 判断该路径是否已出现过
  • 若未出现,则执行 print 并标记为已见

五、实战案例:按访问次数排序输出

场景:将上面的 IP 访问统计按访问次数从高到低排序

awk '{ip[$1]++} END {
    for (i in ip)
        print ip[i], i
}' access.log | sort -nr | head -n 10

输出示例:

150 192.168.1.1
89 192.168.1.2
...

📌 技巧说明:

  • sort -nr:按数字降序排列
  • head -n 10:取前10条记录

六、实战案例:系统用户分类统计(Ubuntu vs CentOS vs EulerOS)

场景:统计 /etc/passwd 中系统用户和普通用户的数量

awk -F: '{
    if ($3 < 1000)
        sys_users++
    else
        normal_users++
} END {
    print "系统用户:", sys_users
    print "普通用户:", normal_users
}' /etc/passwd

输出示例:

系统用户: 45
普通用户: 5

📌 注意事项:

  • Ubuntu、CentOS、EulerOS 默认都使用 UID < 1000 表示系统账户
  • 可根据具体发行版调整阈值(如某些定制系统可能不同)

七、多维数组模拟(GAWK 扩展)

虽然标准 AWK 不支持多维数组,但 GAWK(GNU AWK)可以通过“下标拼接”模拟二维数组。

示例:统计每个 IP 和路径的组合访问次数

awk '{count[$1, $7]++} END {
    for (key in count)
        print key, count[key]
}' access.log

说明:

  • count[$1, $7] 实际上是 count[$1 SUBSEP $7],其中 SUBSEP 是一个特殊字符,默认为 \034
  • 输出形式为:192.168.1.1/index.html 50

八、不同 Linux 发行版注意事项

功能 Ubuntu CentOS EulerOS
awk 实现 gawk gawk gawk
多维数组支持 ✅(gawk) ✅(gawk) ✅(gawk)
字段分隔符默认 空白 空白 空白
/etc/passwd 结构 标准 标准 标准
日志文件位置 /var/log/syslog /var/log/messages /var/log/messages

📌 小贴士:

  • 在 CentOS/EulerOS 上查看 /var/log/messages 需要 sudo
  • 建议先用 head -n 5 filename 查看字段结构再写脚本

九、高级技巧:数组排序函数(需 gawk)

在 gawk 中,可以使用 asort()asorti() 对数组进行排序。

示例:按访问次数排序 IP

awk '
{
    ip[$1]++
}
END {
    n = asort(ip, sorted, "@val_num_desc")
    for (i=1; i<=n; i++) {
        for (key in ip) {
            if (ip[key] == sorted[i]) {
                print key, sorted[i]
            }
        }
    }
}' access.log

⚠️ 注意:asort() 是 GNU 扩展,非 POSIX 标准,确保你的环境支持 gawk


十、调试与优化建议

技巧 说明
print length(array) 查看数组长度(不准确,因为无内置函数)
for (k in array) print k 遍历数组检查键
BEGIN{FS=","} 设置合适的字段分隔符
split() 函数 分割字段用于更复杂的键构造
delete array 清空数组释放内存,适用于大文件处理

✅ 总结

AWK 的数组功能是其最强大的特性之一,尤其适合做日志分析、数据统计、去重处理等工作。通过关联数组的方式,我们可以轻松实现:

  • IP 地址访问统计
  • 请求路径分析
  • 用户行为追踪
  • 系统资源监控

掌握这些技巧后,你可以在 Ubuntu、CentOS、EulerOS 等不同 Linux 系统上高效地进行自动化文本处理和日志分析。

继续练习真实日志文件,结合 grepsortuniq 等命令,你将成为一名真正的 Linux 文本处理高手!🚀

posted @ 2025-06-22 22:46  红尘过客2022  阅读(85)  评论(0)    收藏  举报