5.4.3 报表与字段处理(awk)
3. 报表与字段处理(awk)#
awk 适合按字段解析、统计与生成报表。其核心为“模式 {动作}”,默认以空白分隔字段,可用 -F 指定分隔符。常见内置变量:$0(整行)、$1...$n(字段)、NF(字段数)、NR(行号)、FS/OFS(输入/输出分隔符)。
工作原理草图
安装与验证
- Debian/Ubuntu:
sudo apt-get update
sudo apt-get install -y gawk
awk --version
- RHEL/CentOS/Rocky:
sudo yum install -y gawk
awk --version
关键命令与解释
- 指定分隔符与字段输出:
awk -F':' '{print $1,$3}' /etc/passwd
# -F: 指定输入分隔符
# $1,$3: 输出第1和第3字段
- 计算与统计:
awk '{sum+=$5; n++} END{print "avg:",sum/n}' data.txt
# sum累加第5列,n计数,END块输出平均值
- 格式化输出:
awk '{printf "%-20s %8.2f\n",$1,$5}' data.txt
# 左对齐20字符与保留2位小数
完整可执行示例(报表生成)
1) 准备样例数据:
cat >/tmp/orders.log <<'EOF'
2024-01-01|u01|beijing|99.5|SUCCESS
2024-01-01|u02|shanghai|199.0|FAIL
2024-01-02|u01|beijing|20.0|SUCCESS
2024-01-02|u03|shenzhen|88.0|SUCCESS
EOF
2) 统计城市成交额与成功数:
awk -F'|' '
$5=="SUCCESS"{
city[$3]+=$4;
cnt[$3]++
}
END{
printf "%-10s %8s %6s\n","city","amount","cnt"
for(c in city) printf "%-10s %8.2f %6d\n",c,city[c],cnt[c]
}' /tmp/orders.log | sort -k2 -nr
预期效果
city amount cnt
beijing 119.50 2
shenzhen 88.00 1
访问日志统计示例
- 统计状态码次数:
awk '{code[$9]++} END{for(c in code) print c,code[c]}' /var/log/nginx/access.log | sort -n
- Top IP:
awk '{ip[$1]++} END{for(i in ip) print ip[i],i}' /var/log/nginx/access.log | sort -nr | head
多条件与自定义输出分隔符
awk 'BEGIN{OFS="\t"} $2>=100 && $4~/OK/ {print $1,$2,$NF}' file.txt
# OFS设置输出分隔符为tab;匹配条件后输出字段
排错清单
- 输出字段不对:先查看 NF 与分隔符
awk -F'|' '{print NR,NF,$0}' /tmp/orders.log | head
- 乱码/错列:确认文件编码与分隔符一致(如日志含空格需改为
-F'[ ]+') - 性能慢:先用 awk 过滤,再交给 sort/head
awk '$5=="SUCCESS"' /tmp/orders.log | sort -k4 -nr | head
练习
1. 从 /etc/passwd 中输出用户名与shell,使用 : 分隔。
2. 统计 access.log 中 500 状态码的总数,并输出到 /tmp/500_report.txt。
3. 生成一个 CSV 报表:筛选 SUCCESS 记录并输出 日期,用户,金额。
参考答案(自检用)
# 1
awk -F':' '{print $1,$7}' /etc/passwd
# 2
awk '$9==500{c++} END{print c}' /var/log/nginx/access.log > /tmp/500_report.txt
# 3
awk -F'|' '$5=="SUCCESS"{print $1","$2","$4}' /tmp/orders.log > /tmp/report.csv