1. 概述
AWK 是一种专门用于文本处理的编程语言,也是一个强大的文本分析工具。它诞生于20世纪70年代的贝尔实验室,名称来源于三位创始人 Alfred Aho、Peter Weinberger 和 Brian Kernighan 的姓氏首字母。
特点:
-
专门为文本处理设计
-
行处理软件,适用于扫描、过滤、统计汇总工作
-
数据可以来自标准输入、管道或文件
版本:
-
AWK:原始版本
-
NAWK:New awk,AWK的升级版
-
GAWK:GNU AWK,Linux系统默认版本
在Linux系统上,awk通常是gawk的符号链接:
[root@benet22 opt]# which awk /usr/bin/awk [root@benet22 opt]# ll `which awk` lrwxrwxrwx. 1 root root 4 8月 19 2022 /usr/bin/awk -> gawk
2. 工作原理
AWK逐行读取文本,默认以空格或制表符分隔字段,将分隔后的字段保存到内置变量中,并按模式或条件执行编辑命令。
与sed处理整行不同,AWK倾向于将一行分成多个字段进行处理。它支持逻辑操作符(&&, ||, !)和数学运算(+, -, *, /, %, ^)。
3. 工作流程
3.1 运行模式
任何AWK语句都由模式和动作组成:
-
模式:决定何时触发动作
-
动作:处理数据的具体操作
模式类型:
-
正则表达式:
/root/匹配含有root的行 -
关系表达式:
<,>,&&,||,+,* -
匹配表达式:
~,!~
基本语法:
awk [options] 'BEGIN{ print "start" } pattern{ commands } END{ print "end" }' file
其中BEGIN和END是可选的代码块。
3.2 执行流程
AWK执行流程遵循"读(Read)-执行(Execute)-重复(Repeat)"的循环:
-
读取一行数据
-
根据模式匹配执行相应动作
-
重复直到文件结束
代码块类型:
-
开始块(BEGIN):程序启动时执行一次,用于初始化
-
主体块(Body):对每行输入数据执行
-
结束块(END):程序结束时执行一次,用于汇总
4. 基本语法
4.1 命令格式
awk 选项 '模式或条件{操作}' 文件1 文件2 ...
awk -f 脚本文件 文件1 文件2 ...
4.2 内置变量
AWK提供多种内置变量:
-
FS:输入字段分隔符(默认空格或制表符) -
OFS:输出字段分隔符(默认空格) -
RS:输入记录分隔符(默认换行符) -
ORS:输出记录分隔符(默认换行符) -
NF:当前行的字段数量 -
NR:当前处理的行号 -
FNR:各文件分别计数的行号 -
FILENAME:当前文件名 -
$0:当前行的整行内容 -
$n:当前行的第n个字段
5. 实战案例
5.1 基础文本处理
# 打印文件内容
awk '{print}' zz
# 指定分隔符打印特定字段
awk -F: '{print $5}' zz
# 多个分隔符
awk -F[:/] '{print $9}' zz
# 添加自定义输出格式
awk -F: '{print $1"\t"$2}' /etc/passwd
5.2 内置变量应用
# 打印包含root的行
awk -F: '/root/{print $0}' pass.txt
# 打印行号和内容
awk -F: '{print NR,$0}' pass.txt
# 打印特定行
awk 'NR==2' /etc/passwd
# 打印最后一列
awk -F: '{print $NF}' /etc/passwd
# 统计总行数
awk 'END{print NR}' /etc/passwd
# 格式化输出
awk -F: '{print "第"NR"行有"NF"列"}' /etc/passwd
5.3 生产环境案例
# 提取IP地址
ifconfig ens33 | awk '/netmask/{print "本机的ip地址是"$2}'
# 提取网络流量
ifconfig ens33 | awk '/RX p/{print $5"字节"}'
# 查看磁盘空间
df -h | awk 'NR==2{print $4}'
5.4 BEGIN和END块
# 初始化变量
awk 'BEGIN{x=10;print x}'
# 数学运算
awk 'BEGIN{print 2.5+3.5}'
awk 'BEGIN{print 3**2}'
# 处理前初始化,处理后汇总
awk 'BEGIN{print "开始处理"} {print $1} END{print "处理结束"}' file
5.5 模式匹配
# 正则匹配
awk -F: '/root/' /etc/passwd
# 字段匹配
awk -F: '$1~/root/' /etc/passwd
awk -F: '$7!~/nologin$/{print $1,$7}' /etc/passwd
# 数值比较
awk -F: '$3==0' /etc/passwd
awk -F: '$3>=1000' /etc/passwd
# 逻辑运算
awk -F: '$3<10 || $3>=1000' /etc/passwd
awk -F: 'NR>4 && NR<10' /etc/passwd
5.6 高级用法
# 自定义输入输出分隔符
awk 'BEGIN{FS=":";OFS="---"}{print $1,$2}' pass.txt
# 多文件处理显示行号
awk '{print FNR,$0}' /etc/resolv.conf /etc/hosts
# 修改记录分隔符
awk 'BEGIN{RS=":"}{print $0}' /etc/passwd
# 修改输出行分隔符(多行合并为一行)
awk 'BEGIN{ORS=" "}{print $0}' /etc/passwd