awk
是一种强大的文本处理工具,最初在 Unix 系统上开发,用于模式扫描和处理。它提供了一种编程语言来执行复杂的文本操作,如数据提取、格式化输出以及简单的数据分析。awk
名字来源于其开发者 Alfred Aho、Peter Weinberger 和 Brian Kernighan 的姓氏首字母。
awk
命令执行流程
1. 初始化阶段
- 加载脚本:
awk
首先会读取并解析命令行参数或指定的脚本文件(如果使用了-f
选项)。这包括设置分隔符(通过-F
或内置变量FS
)、定义用户自定义变量(通过-v
)等。 - 打开输入文件:如果没有指定输入文件,则默认从标准输入读取数据。如果有多个输入文件,
awk
将依次处理每一个文件。
2. 逐行读取与处理
awk
按照以下步骤逐行处理输入文件中的每一行:
2.1 分割记录(行)
- 读取一行:每次循环开始时,
awk
从当前输入文件中读取一行作为当前记录(行)。 - 分割字段:根据设定的字段分隔符(
FS
),将当前记录分割成若干个字段,并存储在$1
,$2
, …,$n
中,其中$0
表示整个记录(即整行文本)。
2.2 应用模式匹配
对于每条规则(即 pattern {action}
),awk
执行如下操作:
- 检查模式:如果指定了模式(可以是正则表达式、条件表达式或它们的组合),
awk
会对当前记录进行评估。只有当模式为真时,才会执行相应的动作{action}
。 - 默认行为:如果没有指定模式,则默认情况下所有记录都会被视为匹配,从而执行对应的
{action}
。如果没有指定动作,默认动作为{print $0}
,即将当前记录打印出来。
2.3 执行动作
一旦模式匹配成功,awk
就会执行相应的动作。动作可以包含任何合法的 awk
语句,如:
- 打印输出:如
print
或printf
。 - 计算与赋值:对变量进行算术运算或赋值。
- 控制结构:如
if
、for
、while
等,用于实现逻辑判断和循环。 - 退出程序:如
exit
,用于提前终止awk
程序的执行。
3. 结束处理
- END 模式:在处理完所有输入记录之后,
awk
会检查是否存在END
模式的代码块。如果有,将会执行这些代码。通常用于总结性的输出,比如计算总和、平均值等。
示例流程
假设有一个名为 data.txt
的文件,内容如下:
Alice 30
Bob 25
Charlie 35
并且运行以下 awk
命令:
awk 'BEGIN {print "Start Processing..."}
{sum += $2; print $1, $2}
END {print "Total age:", sum}' data.txt
执行流程详解
-
初始化阶段:
- 加载脚本并设置初始状态。
- 打开
data.txt
文件准备读取。
-
逐行读取与处理:
-
第一行 (
Alice 30
):- 分割字段:
$1 = "Alice"
,$2 = "30"
- 检查模式:无模式,直接执行动作。
- 执行动作:累加年龄到
sum
变量,并打印Alice 30
。
- 分割字段:
-
第二行 (
Bob 25
):- 分割字段:
$1 = "Bob"
,$2 = "25"
- 检查模式:同上。
- 执行动作:累加年龄到
sum
变量,并打印Bob 25
。
- 分割字段:
-
第三行 (
Charlie 35
):- 分割字段:
$1 = "Charlie"
,$2 = "35"
- 检查模式:同上。
- 执行动作:累加年龄到
sum
变量,并打印Charlie 35
。
- 分割字段:
-
-
结束处理:
- 执行
END
模式下的代码块:打印Total age: 90
。
- 执行
基本语法
awk [options] 'pattern {action}' filename
- pattern:决定哪些行会被处理。它可以是正则表达式、条件表达式或两者结合。
- action:对匹配的行执行的操作。如果没有指定
action
,默认会打印匹配的行。 - filename:输入文件名。如果没有提供文件名,
awk
会从标准输入读取数据。
常用选项
-F fs
或--field-separator=fs
:指定字段分隔符(默认为空格或制表符)。-v var=value
:定义一个变量并赋值。-f scriptfile
:从脚本文件中读取awk
脚本。
内置变量
awk
提供了一些有用的内置变量,可以帮助进行更复杂的文本处理:
- FS:字段分隔符,默认是空白字符(空格或制表符)。可以通过
-F
或在脚本中设置FS=","
来更改。 - OFS:输出字段分隔符,默认为空格。可以修改为其他符号,例如
,
。 - NR:当前记录(行)编号。
- NF:当前记录中的字段数量。
- $0