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