一、awk 是什么?
awk 是一种文本处理工具和编程语言,专门用于对结构化文本(如表格、日志)进行格式化处理、报告生成和数据提取。
名字来源
取自三位创始人:Aho、Weinberger、Kernighan 的姓氏首字母
二、awk 的核心功能
| 功能 | 说明 |
|---|---|
| 按列处理 | 自动将每行分割成字段,通过 $1、$2 访问 |
| 模式匹配 | 支持正则表达式,只处理匹配的行 |
| 条件过滤 | 根据条件筛选数据 |
| 数学计算 | 支持求和、平均值等运算 |
| 格式化输出 | 自定义输出格式(类似 C 语言的 printf) |
| 关联数组 | 可以使用字符串作为下标 |
| 流程控制 | 支持 if、for、while 等语句 |
三、awk 的命令格式
基本语法
awk [选项] '模式 {动作}' 文件名
完整格式
awk [选项] 'BEGIN{初始化} 模式 {动作} END{收尾}' 文件名
常用选项
| 选项 | 作用 |
|---|---|
-F | 指定字段分隔符(默认空白符) |
-v | 定义变量 |
-f | 从文件读取 awk 脚本 |
四、awk 的处理流程
执行流程三步曲
开始执行
↓
┌─── BEGIN 块(只执行一次)
↓ ↓
读取第一行 → 模式匹配? → 匹配则执行动作
↓ ↓
读取第二行 → 模式匹配? → 匹配则执行动作
↓ ↓
... ...
↓ ↓
读取最后一行 → 模式匹配? → 匹配则执行动作
↓
─── END 块(只执行一次)
↓
结束
三个关键块
| 块 | 执行时机 | 用途 |
|---|---|---|
| BEGIN | 读取文件之前执行 | 初始化变量、打印表头、设置分隔符 |
| 主块 | 对每一行执行 | 核心处理逻辑 |
| END | 读取文件之后执行 | 输出汇总结果 |
五、awk 的内置变量
常用内置变量
| 变量 | 含义 |
|---|---|
$0 | 整行内容 |
$1、$2… | 第1、2…个字段 |
NF | 当前行的字段数(Number of Fields) |
NR | 当前行号(Number of Record,从1开始) |
FNR | 当前文件的行号(多文件时) |
FS | 字段分隔符(Field Separator,默认空白) |
OFS | 输出字段分隔符(Output Field Separator,默认空格) |
RS | 记录分隔符(Record Separator,默认换行) |
ORS | 输出记录分隔符(Output Record Separator,默认换行) |
六、awk 的运算符
比较运算符
| 运算符 | 代表意义 |
|---|---|
> | 大于 |
< | 小于 |
>= | 大于或等于 |
<= | 小于或等于 |
== | 等于 |
!= | 不等于 |
逻辑运算符
| 运算符 | 代表意义 |
|---|---|
&& | 逻辑与(AND) |
|| | 逻辑或(OR) |
! | 逻辑非(NOT) |
正则匹配运算符
| 运算符 | 代表意义 |
|---|---|
~ | 匹配正则表达式 |
!~ | 不匹配正则表达式 |
七、基础示例
示例文件 dataf3
张三 85 92 88
李四 78 88 90
iivey 95 89 92
王五 92 96 94
1. 查找包含特定关键词的行
awk '/iivey/' dataf3
# 显示含 iivey 的数据行
# 输出:iivey 95 89 92
2. 打印指定字段
awk '{ print $1, $2 }' dataf3
# 显示每一行的第 1 和第 2 个字段
# 输出:
# 张三 85
# 李四 78
# iivey 95
# 王五 92
3. 条件筛选后打印指定字段
awk '/iivey/{ print $1, $2 }' dataf3
# 将含有 iivey 关键词的数据行的第 1 及第 2 个字段显示出来
# 输出:iivey 95
4. 指定分隔符
awk -F: '/^iivey/{ print $3, $4 }' /etc/passwd
# 使用选项 -F,指定 : 为分隔字符
# 显示账号 iivey 的 uid(第 3 字段)及 gid(第 4 字段)
5. 使用 BEGIN 设置输出分隔符
awk -F: 'BEGIN{OFS="+++"}/^iivey/{ print $1, $2, $3, $4, $5 }' /etc/passwd
# 以 : 为分隔字符,+++ 为输出字段分隔符
# 将账号 iivey 的第 1~5 栏显示出来
# 执行结果:iivey+++x+++1002+++1002+++
6. 使用 NF 和 NR 变量
last -n 5 | awk '{print $1 "\t lines: " NR "\t columns: " NF}'
# 显示前5行登录记录,同时输出行号和字段数
# 输出:
# root lines: 1 columns: 10
# root lines: 2 columns: 10
# root lines: 3 columns: 10
# root lines: 4 columns: 10
# root lines: 5 columns: 10
注意:在 awk 内的 NR、NF 等变量要用大写,且不需要有 $ 符号!
八、BEGIN 和 END 的详细用法
BEGIN 的作用
在 awk 开始扫描输入之前执行,通常用于:
- 初始化变量
- 设置字段分隔符(FS)
- 打印表头
END 的作用
在 awk 扫描完全输入之后执行,通常用于:
- 输出汇总结果
- 打印统计信息
示例:设置分隔符的问题
# 错误示例:FS 设置太晚,第一行没生效
cat /etc/passwd | awk '{FS=":"} $3 < 10 {print $1 "\t " $3}'
# 第一行输出:root:x:0:0:root:/root:/bin/bash (没分割)
# 正确示例:用 BEGIN 提前设置 FS
cat /etc/passwd | awk 'BEGIN{FS=":"} $3 < 10 {print $1 "\t " $3}'
# 输出:
# root 0
# bin 1
# daemon 2
# adm 3
示例:指定行号范围
# 显示第 6 行
cat /etc/passwd | awk 'BEGIN{FS=":"} NR==6{print $1 "\t " $3}'
# 输出:sync 5
# 显示前 4 行
cat /etc/passwd | awk 'BEGIN{FS=":"} NR<=4{print $1 "\t " $3}'
# 输出:
# root 0
# bin 1
# daemon 2
# adm 3
九、实战综合示例(统计销售金额)
示例文件 bb.txt
一:50件:200.00
二:60件:300.00
三:70件:400.00
awk 统计脚本
awk 'BEGIN{
FS=":"; # 设置分隔符为冒号
print "统计销售金额"; # 打印表头
total=0 # 初始化总金额
}
{
print $3; # 打印每行的金额
total=total+$3 # 累加金额
}
END{
printf "销售金额总计:%.2f\n", total # 输出总计
}' bb.txt
执行结果
统计销售金额
200.00
300.00
400.00
销售金额总计:900.00
解析
- BEGIN 块:初始化分隔符 FS、打印表头、初始化 total 变量
- 主块:对每一行执行,打印第 3 字段(金额)并累加到 total
- END 块:所有行处理完后,输出总金额(保留两位小数)
十、常用系统信息获取示例
1. 取得网卡的 IP
ifconfig | grep 'inet addr:' | grep Bcast | awk '{print $2}' | awk -F: '{print $2}'
# 先找到包含 IP 的行,提取第 2 字段,再用冒号分割取第 2 部分
2. 取得网络设备名称
cat /proc/net/dev | awk -F: '/eth.:|ppp.:|wlan.:/{print $1}'
# -F: 把分隔符设为冒号
# 正则表达式 /eth.:|ppp.:|wlan.:/ 匹配多种网卡设备
# 找到后去掉冒号,取第一个字段,得到设备名(eth0、ppp1、wlan1)
3. 取得系统内存大小
cat /proc/meminfo | awk '/MemTotal/{print $2}'
# 找到包含 MemTotal 的行,打印第 2 字段(内存大小数值)
# /proc/meminfo 内容示例:MemTotal: 223128 kB
十一、awk 使用注意事项
引号的使用
awk 的所有动作以单引号 ' 括住。如果需要 print 打印非变量的文字,必须使用双引号括起来:
awk '{print "用户名: " $1 "\t 行号: " NR}'
变量引用
- 内置变量(NR、NF、FS 等)不需要加
$符号 - 字段变量($1、$2、$0)需要加
$符号
多个命令
如果需要在 awk 中执行多个命令,用分号 ; 分隔:
awk 'BEGIN{FS=":"; OFS="+++"} {print $1, $2}'
十二、awk 与 grep、sed 对比
| 工具 | 擅长 | 不擅长 |
|---|---|---|
| grep | 快速查找行 | 修改内容、列处理 |
| sed | 行编辑、替换 | 列计算、统计 |
| awk | 列处理、计算、报表、格式化输出 | 简单查找(不如 grep 快) |
组合使用
# grep 筛选行,awk 处理列
grep "ERROR" app.log | awk '{print $1, $4}' | sort | uniq -c
十三、一句话总结
awk 是文本处理神器,按行读取、自动分列,通过模式匹配和动作处理数据,支持 BEGIN/END 块做初始化和收尾工作,特别适合做统计、格式化输出和报表生成。
发表回复