命令awk

Source

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)"的循环:

  1. 读取一行数据

  2. 根据模式匹配执行相应动作

  3. 重复直到文件结束

代码块类型

  • 开始块(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