awk作为Linux文本处理“三剑客”(grep、sed、awk)的天花板,是文本分析、日志切割、数据统计、报表生成的终极神器。相比于grep检索、sed替换,awk更擅长列操作、数值计算、逻辑判断,能一行命令搞定复杂文本处理,是运维、开发、数据分析人员的必备技能。很多人觉得awk语法晦涩、变量难记,要么不敢上手,要么只会简单打印列,白白浪费这款神器。这篇教程彻底摒弃枯燥理论,全程零门槛白话讲解+全场景实战案例+避坑警示,覆盖99%日常工作需求,新手看完就能上手,老手可当速查手册,建议直接收藏转发,处理文本时随时翻。
别再怕awk复杂!这篇全实战教程,文本统计/日志分析/列操作,1行命令搞定复杂数据- 日志文件按列筛选、求和、求平均值,手动计算耗时又易错
- awk语法奇怪,BEGIN/END、$0/$1分不清,写命令频频报错
- 零基础吃透awk核心逻辑,弄懂BEGIN/MAIN/END三大模块
- 掌握列操作、条件筛选、数值计算、文本格式化全场景用法
- 避开80%新手高频坑,分隔符、变量、语法错误一键解决
- 附赠速查表+面试真题+运维实战脚本,工作备考双适配
Linux零基础小白、运维工程师、后端/测试开发、日志分析师、运维面试备考者
先搞懂awk的底层逻辑和基础规则,理解原理再记命令,事半功倍,全程大白话无晦涩术语。awk是一门文本处理编程语言(名字取自三位作者Alfred Aho、Peter Weinberger、Brian Kernighan),核心定位是逐行扫描文本、按列拆分数据、执行逻辑处理、输出结果。核心优势:支持列操作、数值计算、逻辑判断、循环数组,不用写复杂脚本,一行命令就能完成复杂文本分析,处理大文件速度极快。awk处理文本分三大模块,固定流程,理解这3步,再也不会写乱语法:- BEGIN模块:处理文本前执行,常用于初始化变量、打印表头
- MAIN主模块:逐行处理文本,逐行读取、按列拆分、执行筛选/计算
- END模块:处理完所有文本后执行,常用于统计结果、打印汇总
awk [选项参数] 'BEGIN{初始化} 条件{执行动作} END{汇总输出}' 目标文件
- 记录(Record):awk默认按换行拆分,一行就是一条记录,用$0表示整行
- 字段(Field):awk默认按空格/制表符拆分列,$1代表第1列,$2代表第2列,$NF代表最后一列
- 分隔符(FS):默认空格/制表符,可自定义(如逗号、冒号、横杠)
- 内置变量:无需定义直接用,比如NR(行号)、NF(列数)、FS(字段分隔符)
新建`awk_test.txt`测试文件,模拟服务器日志/报表数据,后续所有命令均基于此演示:cat > awk_test.txt << EOF
#姓名 部门 薪资 工龄
张三 运维 8000 3
李四 开发 12000 5
王五 测试 9000 2
赵六 运维 10000 4
孙七 开发 15000 6
EOF
二、核心高频命令:按场景分类,学完直接用(干货主体)本章按使用频率从高到低拆分,每个命令带格式+实战案例+代码注释+执行效果,贴合运维、开发日常场景,可直接复制套用。awk最核心的用法就是按列提取、打印,解决文本列筛选需求,是日常最常用的功能。# 打印整行内容(等价于cat 文件名)
awk'{print $0}' awk_test.txt
# 打印第1列、第3列(姓名+薪资),用空格分隔
awk '{print $1,$3}' awk_test.txt
# 打印最后一列(工龄),$NF代表最后一列
awk '{print $NF}' awk_test.txt
# 打印倒数第二列(薪资)
awk '{print $(NF-1)}' awk_test.txt
# NR代表当前行号,打印行号+姓名+部门
awk'{print NR,$1,$2}' awk_test.txt
# 用制表符分隔,格式化输出
awk '{print "姓名:"$1"\t部门:"$2"\t薪资:"$3}' awk_test.txt
awk默认按空格/制表符拆分,遇到逗号、冒号、横杠等分隔符,需手动指定分隔符。# 模拟冒号分隔文件(/etc/passwd格式),提取用户名+shell
echo"root:x:0:0:root:/root:/bin/bash" | awk -F ':''{print $1,$7}'
# 多分隔符:同时按空格和=拆分(适配配置文件)
echo "port=8080 user=admin" | awk -F '[ =]''{print $2,$4}'
# BEGIN中定义FS(字段分隔符)为逗号
awk'BEGIN{FS=","} {print $1,$2}' 逗号分隔文件.csv
按条件过滤行,只打印符合要求的数据,适配日志筛选、数据过滤场景。# 筛选薪资大于10000的员工
awk'$3>10000 {print $1,$3}' awk_test.txt
# 筛选工龄等于3年的员工
awk '$NF==3 {print $1,$NF}' awk_test.txt
# 筛选薪资在9000-12000之间的员工
awk '$3>=9000 && $3<=12000 {print $1,$3}' awk_test.txt
# 筛选部门为运维的员工(模糊匹配)
awk'$2~/运维/ {print $1,$2}' awk_test.txt
# 筛选部门不是开发的员工(!~表示不匹配)
awk '$2!~/开发/ {print $1,$2}' awk_test.txt
# 精确匹配部门为测试的员工
awk '$2=="测试" {print $1,$2}' awk_test.txt
# 打印第2-4行内容
awk'NR==2,NR==4 {print NR,$0}' awk_test.txt
awk内置算术运算,支持求和、求平均值、最大值、最小值,这是grep/sed做不到的核心功能。# 初始化sum变量,逐行累加薪资,END模块打印总和
awk'BEGIN{sum=0} {sum+=$3} END{print "薪资总和:",sum}' awk_test.txt
# 求薪资平均值、总人数
awk'{sum+=$3;count++} END{print "总人数:",count,"平均薪资:",sum/count}' awk_test.txt
# 求最高薪资
awk 'NR==1{max=$3} $3>max{max=$3} END{print "最高薪资:",max}' awk_test.txt
# 按部门分组,统计各部门薪资总和
awk'{sum[$2]+=$3} END{for(i in sum) print i"部门薪资总和:",sum[i]}' awk_test.txt
模块5:高阶——BEGIN/END模块实战(格式化输出)# BEGIN打印表头,END打印汇总,完整报表格式
awk 'BEGIN{print "====员工薪资报表====";print "姓名\t部门\t薪资"} {print $1"\t"$2"\t"$3} END{print "====报表结束===="}' awk_test.txt
awk搭配管道符,处理其他命令输出结果,是运维日常排查、统计的核心用法。# 1. 查看内存使用率,提取已用内存
free -h | awk 'NR==2{print "内存已用:",$3}'
# 2. 查看CPU占用率,提取空闲CPU
top -bn1 | awk 'NR==3{print "空闲CPU:",$4}'
# 3. 统计Nginx访问日志IP访问次数(高频运维)
awk '{print $1}' access.log | sort | uniq -c | sort -nr
# 4. 筛选占用内存前10的进程
ps aux | awk '{print $4,$11}' | sort -nr | head -10
本章还原真实运维、开发场景,所有命令可直接复制到服务器执行,解决日常痛点。# 1. 统计访问日志中各IP访问次数(降序)
awk '{print $1}' /var/log/nginx/access.log | sort | uniq -c | sort -nr
# 2. 提取状态码为404的请求URL
awk '$9==404 {print $7}' /var/log/nginx/access.log
# 3. 统计某日访问总量
awk '$4~/2026-03-22/ {count++} END{print "当日访问量:",count}' /var/log/nginx/access.log
# 1. 统计磁盘使用率,超过80%告警
df -h | grep -v tmpfs | awk '{if($5>80) print "磁盘告警:",$1,$5}'
# 2. 统计在线用户数
who | awk 'END{print "在线用户数:",NR}'
# 3. 提取CPU型号信息
cat /proc/cpuinfo | awk -F ':''/model name/{print $2}' | head -1
# 1. 提取配置文件中的端口号
grep -E 'port|listen' nginx.conf | awk -F '=''{print $2}' | tr -d ';'
# 2. 批量修改配置文件数值(配合sed)
awk -F '=''$1=="max_connections"{print $1"=1000"}' my.cnf > temp.cnf
# 自动化日志统计脚本片段
#!/bin/bash
log_file="/var/log/app.log"
error_count=$(awk '/ERROR/{count++} END{print count}'"$log_file")
echo"今日错误日志数量:$error_count"
if [ $error_count -gt 10 ];then
echo"错误日志超标,请注意排查!"
fi
💡坑1:$符号使用错误
原因:$后面必须跟数字/变量,不能直接跟字符串,变量取值不用加$
错误:awk '{print $name}' test.txt正确:awk '{name=$1; print name}' test.txt💡坑2:分隔符不生效
原因:多分隔符未用[]包裹,特殊符号未转义
错误:awk -F ', ' '{print $1}' test.txt正确:awk -F '[ ,]' '{print $1}' test.txt💡坑3:数值计算结果异常
原因:文本含非数字字符,或变量未初始化解决:BEGIN模块初始化数值变量,过滤非数字行💡坑4:Mac系统awk语法报错
原因:Mac自带awk为BSD版,部分语法和GNU awk差异解决:brew install gawk安装GNU awk,用gawk替代awk- 大括号、引号必须成对出现,单引号包裹awk命令主体
| |
| |
| awk -F ':' '{print $1}' file |
| awk '$2>100 {print $0}' file |
| awk '{sum+=$3} END{print sum}' file |
| awk '$1~/关键词/ {print}' file |
| awk 'NR==2,NR==5 {print}' file |
- awk中NR、NF、$0、$NF分别代表什么含义?
- awk的BEGIN和END模块分别在什么时候执行?
- 如何用awk筛选日志中包含指定关键词的行,并打印第2列和最后一列?
awk的核心就是“按行读取、按列拆分、条件动作、汇总输出”,日常工作记住-F分隔符、print打印、NR/NF内置变量、求和统计,足以应对90%的文本处理场景。新手牢记:先打印列验证、再加条件筛选、最后统计汇总。