Shell 四剑客之三:awk 文本处理实战
awk 是按列处理文本的利器:日志统计、报表生成、字段提取都靠它。它把每一行按分隔符切成字段,$1、$2 随取随用,还能求和计数。这篇讲 awk 的基本结构、字段提取、统计和日志分析实战。
一、基本结构
# 模式 {动作}:匹配的行执行动作
awk '/ERROR/ {print $0}' app.log
# 常用内置变量
# $0 整行,$1 第 1 列,$2 第 2 列,NF 列数,NR 行号
# -F 指定分隔符,BEGIN 开始前执行,END 结束后执行
awk -F: '{print $1, $3}' /etc/passwd # 冒号分隔,取用户名和 UID
awk '{print NR, $0}' file.txt # 每行前面加行号
记住三个变量就够入门:$0 是整行,$N 是第 N 列,NF 是这行有几列。分隔符默认是空白,冒号、逗号用 -F 指定。
二、字段提取与格式化
# 取第 1 列和第 3 列,逗号分隔
awk '{print $1, $3}' data.txt
# printf 格式化输出,对齐成表格
awk '{printf "%-15s %8d\n", $1, $2}' data.txt
# 拼接字段
awk '{print $2 "@" $1}' users.txt
# 只打印最后一列(NF 是列数,$NF 就是最后一列)
awk '{print $NF}' data.txt
# 逗号分隔的 CSV,取第 2 列
awk -F, '{print $2}' data.csv
三、统计:求和、计数、平均
# 第 2 列求和
awk '{sum += $2} END {print sum}' data.txt
# 求平均
awk '{sum += $2; n++} END {print sum / n}' data.txt
# 计数:每种状态各出现几次
awk '{count[$1]++} END {for (k in count) print k, count[k]}' status.txt
# 找最大值所在的行
awk '$3 > max {max = $3; line = $0} END {print line}' data.txt
END {} 是统计的关键:处理过程中累加,结束后一次性输出结果。数组 count[$1]++ 是 awk 的招牌写法,按某个字段分组计数一行搞定。
四、条件与关联数组
# 只处理第 3 列大于 100 的行
awk '$3 > 100 {print $0}' data.txt
# if-else:按数值分档
awk '{if ($2 >= 90) print $1, "优秀"; else if ($2 >= 60) print $1, "及格"; else print $1, "不及格"}' score.txt
# 关联数组:按 IP 统计请求数,再按次数排序
awk '{ip[$1]++} END {for (k in ip) print ip[k], k}' access.log | sort -nr | head
五、实战:日志分析
# 统计各状态码出现次数(假设第 9 列是状态码)
awk '{code[$9]++} END {for (k in code) print k, code[k]}' access.log | sort -nr
# 统计访问量 Top 10 的 IP
awk '{ip[$1]++} END {for (k in ip) print ip[k], k}' access.log | sort -nr | head -10
# 算平均响应时间(假设第 10 列是耗时,单位毫秒)
awk '{sum += $10; n++} END {print "平均耗时:", sum / n "ms"}' access.log
# 找慢请求:耗时超过 1000ms 的行
awk '$10 > 1000 {print $0}' access.log | head -20
awk 的精髓是“按列思考”:先想清楚你要第几列,再想对它做什么。日志分析、报表统计、字段提取,这三类活 awk 一行就能干,别急着写 Python。
声明:本站所有文章,如无特殊说明或标注,均为本站原创发布。任何个人或组织,在未征得本站同意时,禁止复制、盗用、采集、发布本站内容到任何网站、书籍等各类媒体平台。如若本站内容侵犯了原著者的合法权益,可联系我们进行处理。







