Linux awk 命令详解与实战:字段分割、条件过滤与数据统计


日志要按列提取、统计报表要算总和、两个文件要按关键字关联——用 grep 只能整行过滤,用 awk 才能按字段切分、计算、重组输出。awk 是 Linux 文本处理三剑客(grep、sed、awk)里功能最强大的一个,本质是一门小型编程语言。这篇文章从最常用的字段操作讲起,带你快速上手 awk 的实战用法。

一、awk 核心概念:按字段处理

awk 默认按空白(空格/Tab)把每一行拆成多个字段,$1 是第一个字段、$2 是第二个、$0 是整行:

awk '{print $1}' /var/log/nginx/access.log      # 打印每行第一个字段(IP)
awk '{print $1, $9}' access.log                  # 打印 IP 和状态码
awk '{print $0}' access.log                      # 打印整行(等价于 cat)

比如 Nginx 日志行 192.168.1.1 - - [18/Sep/2026:10:00:00] "GET / HTTP/1.1" 200 1234,$1 是 IP、$9 是状态码、$10 是响应字节数。

指定分隔符:字段默认按空白切分,用 -F 可以改成任意字符:

awk -F: '{print $1}' /etc/passwd                # 按冒号切分,取用户名
awk -F'[" "]' '{print $6}' access.log           # 多分隔符,提取请求方法
awk -F, '{print $2}' data.csv                   # 处理 CSV 文件

二、常用内建变量

变量 含义
$0 整行内容
$1~$N 第 N 个字段
NF 当前行的字段总数
NR 已处理的行号(从 1 开始)
FS 输入分隔符(同 -F)
OFS 输出分隔符,默认空格
BEGIN 开始处理前执行一次
END 全部处理完后执行一次
awk '{print NF}' file                            # 每行有几个字段
awk 'NR==1' file                                 # 打印第一行
awk '{print NR, $0}' file                        # 带行号输出
awk 'BEGIN{OFS="--"}{print $1, $2}' file         # 自定义输出分隔符

三、条件过滤:比 grep 更灵活

awk 支持在花括号前加条件,只处理符合条件的行:

awk '$9 == 500' access.log                       # 只输出状态码 500 的行
awk '$9 >= 500 {print $1, $9, $7}' access.log    # 5xx 错误,输出 IP+状态码+URL
awk '$10 > 100000 {print $1, $10}' access.log    # 响应超过 100KB 的请求
awk '/error|exception/ {print NR, $0}' app.log   # 正则匹配
awk 'NR > 1 && NR <= 10' file                    # 输出第 2 到 10 行
awk '$1 != "127.0.0.1"' access.log               # 排除指定 IP

支持 ==、!=、>、<、>=、<=、&&、||、!,以及正则 /pattern/。

四、实战场景

1. 统计日志里的状态码分布

awk '{count[$9]++} END {for (code in count) print code, count[code]}' access.log

按状态码分组计数,输出形如 200 15320、404 321 的结果。

2. 计算平均响应时间 / 求和

awk '{sum += $10} END {print "总流量:", sum/1024/1024, "MB"}' access.log
awk '{sum += $10; n++} END {print "平均字节数:", sum/n}' access.log

3. 提取并去重 IP 列表

awk '{print $1}' access.log | sort | uniq -c | sort -rn | head

排在最上面的就是访问量最高的 IP,配合 awk '$1 > 100' 可快速发现异常刷量。

4. 分析 /etc/passwd 用户

awk -F: '$3 >= 1000 {print $1, $3}' /etc/passwd    # 找出普通用户(UID>=1000)
awk -F: '{print $1, $7}' /etc/passwd               # 用户名和登录 Shell

5. 报表生成:计算每台服务器的错误数

awk '{if ($9 >= 500) err[$1]++} END {for (ip in err) print ip, err[ip]}' access.log

6. 文件间关联(类似 join)

awk 'NR==FNR {name[$1]=$2; next} {print $1, name[$1]}' id_name.txt data.txt

先读第一个文件建映射,再处理第二个文件按 key 关联,常用于合并两个列表。

五、进阶:printf 格式化输出

awk '{printf "%-15s %s\n", $1, $9}' access.log     # 左对齐 15 位
awk '{printf "%.2f MB\n", $10/1024/1024}' access.log   # 保留两位小数
awk 'BEGIN{printf "%-8s %-6s\n", "状态码", "数量"}'

写报表、对齐列输出时 printf 比 print 好用得多。

六、常见坑与建议

  1. 花括号位置:awk '条件 {动作}',条件在外面、动作在花括号里,两者都写反了就是语法错误;
  2. 变量默认是字符串:$9 == 500 时 awk 会自动转数值比较,但要小心带引号的比较 $9 == "500" 是字符串比较,行为不同;
  3. 大文件:awk 处理 GB 级日志没问题,但 END 里累加太多键(如海量 IP)会占内存,可以用 sort | uniq -c 分流;
  4. 单引号转义:awk 脚本整体用单引号包裹,脚本内想用单引号(如字符 ' ')比较麻烦,必要时改用双引号包外层并转义。

总结:awk 一句话概括就是"按列处理文本"。入门记住三条——$1 取字段、-F 定分隔符、条件 {动作} 过滤,再配合 BEGIN/END 做统计,日志分析、报表计算、文件关联这些活儿都能轻松拿下。比起 grep 只能"整行过滤",awk 能"拆开重组",是运维必会的第二把文本刀。


手机扫码阅读

微信或手机浏览器扫一扫,随时随地随心阅读与分享

宝塔面板安装与使用教程:从零搭建网站、SSL证书与定时备份

Linux grep 命令详解与实战:文本搜索、正则匹配与多文件批量处理

评 论
更换验证码