awk 完整介绍及详细示例

一、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

解析

  1. BEGIN 块:初始化分隔符 FS、打印表头、初始化 total 变量
  2. 主块:对每一行执行,打印第 3 字段(金额)并累加到 total
  3. 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 块做初始化和收尾工作,特别适合做统计、格式化输出和报表生成。

发表回复

您的邮箱地址不会被公开。 必填项已用 * 标注