一、基础介绍
定义
awk是文本处理编程语言,擅长按行、按列解析日志、配置文件,是三剑客(grep、sed、awk)里最强大的数据筛选工具。
- 核心定位:分列处理、统计计算、格式化输出
- 工作模式:逐行扫描文件,默认以空格/制表符分割字段。
- 主流版本:gawk(GNU awk,Linux默认)、nawk、mawk。
语法格式
awk [选项] '条件{动作}' 文件名 # 标准完整版 awk [OPTIONS] 'BEGIN{初始化} 匹配规则{执行主体} END{收尾统计}' fileBEGIN{}:读取文件之前执行,只运行1次,常用于定义变量、打印表头。{}主体:逐行读取文本,匹配成功就执行内部代码。END{}:文件读取结束后执行1次,用于汇总、求和、平均值。
二、内置常用变量(最常用)
字段变量(列)
变量 | 含义 |
| 整行全部内容 |
| 第1列, |
| 当前行总列数, |
| 倒数第二列 |
行变量
变量 | 含义 |
| 全局行号,多文件叠加计数 |
| 单个文件行号,多文件重新从1计数 |
| 输入分隔符,默认空格,等价 |
| 输出分隔符,默认空格 |
| 行分隔符(默认换行) |
| 输出行分隔符(默认换行) |
三、常用命令选项
- -F 指定分隔符(高频)
# 逗号分割,取第1、3列 awk -F ',' '{print $1,$3}' test.txt # 多分隔符:空格、:、/ 都作为分割 awk -F '[: /]' '{print $1}' test.txt- -v 自定义外部变量
awk -v num=10 '{print $1+num}' test.txt-f调用awk脚本文件
awk -f test.awk test.txt四、基础实操示例
简单打印列
# 打印整行 awk '{print $0}' test.txt # 打印第2、最后一列 awk '{print $2,$NF}' test.txt # 打印行号+内容 awk '{print NR,$0}' test.txt分隔符案例
# /etc/passwd 以:分割,打印用户名($1)和shell($7) awk -F ':' '{print $1,$7}' /etc/passwd行过滤(条件筛选)
数值比较
# 筛选第3列数值大于100的行 awk '$3>100 {print $0}' test.txt # 行号小于10的行 awk 'NR<10' test.txt字符串匹配(~匹配、!~不匹配)
# 包含root的行 awk '$0 ~ /root/' /etc/passwd # 第1列不是ftp的行 awk '$1 !~ /ftp/' /etc/passwd # 精准匹配 awk '$1=="root"' /etc/passwd多条件 && ||
# 第2列>20 且 第3列<100 awk '$2>20 && $3<100 {print}' test.txtBEGIN 与 END 用法
# 打印表头+内容+结尾统计行数 awk 'BEGIN{print "姓名 账号 shell"} -F ":" {print $1,$3,$7} END{print "一共",NR,"个用户"}' /etc/passwd # 求和:统计第2列总和 awk '{sum+=$2} END{print "总和:",sum}' test.txt # 求平均值 awk '{sum+=$2;count++} END{print sum/count}' test.txt五、格式化输出 printf
print简单换行;printf精准排版,语法和C语言一致
# %s字符串 %d整数 %f浮点数 \t制表符 \n换行 awk -F ':' '{printf "用户名:%-10s 编号:%d\n",$1,$3}' /etc/passwd常用格式符:
%s字符串、%d整数、%.2f保留2位小数%-10s左对齐占10字符,%10s右对齐
六、awk 流程控制(if/for/while)
if 判断
# 第3列大于10输出大,否则输出小 awk '{if($3>10) print $1,"大";else print $1,"小"}' test.txt # 多分支 awk '{ if($1=="root") print "管理员"; else if($1=="ftp") print "ftp用户"; else print "普通用户" }' /etc/passwdfor 循环
# 遍历一行所有列,打印每一列 awk '{for(i=1;i<=NF;i++) print $i}' test.txt七、数组(awk 核心,常用于去重、统计)
awk数组为关联数组(哈希),下标可以是字符串/数字
# 统计日志中IP出现次数($1为IP) awk '{ip[$1]++} END{for(i in ip) print i,ip[i]}' access.log # 文本去重 awk '!a[$0]++' test.txt八、高频生产实战案例
案例1:查看系统内存使用率
free | awk '/Mem/{print "使用率:",$3/$2*100,"%"}'案例2:统计nginx访问IP频次并排序
awk '{ip[$1]++} END{for(k in ip)print ip[k],k}' access.log | sort -nr案例3:筛选空行、删除空行
# 打印非空行 awk 'NF>0' test.txt # 空行计数 awk '/^$/{n++} END{print "空行数量:",n}' test.txt案例4:筛选指定行区间
# 第10~20行 awk 'NR>=10 && NR<=20' test.txt案例5:计算磁盘总占用
df -h | awk '/^\/dev/{sum+=$5} END{print sum}'九、常用简写技巧
awk '1' file等价awk '{print $0}'打印全部行awk '0' file不输出任何内容!a[$0]++万能去重sum+=$n快速累加求和
十、易错点总结
- 分隔符含特殊字符(
* . +)要用正则转义; - 字符串比较必须用
==,单个=是赋值; - BEGIN 只在开头执行,无法读取文件内容;
- NR多文件持续累加,FNR单文件重置为1。