Awk是一种用于高级文本处理的通用脚本语言。 它主要用作报告和分析工具。
与大多数其他程序性编程语言不同,awk是数据驱动的,这意味着您定义了一组针对输入文本要执行的操作。 它获取输入数据,对其进行转换,然后将结果发送到标准输出。
本文介绍了awk编程语言的基本知识。 了解awk的基础知识将大大提高您在命令行上操作文本文件的能力。
Awk运作方式
awk有几种不同的实现。 我们将使用awk的GNU实现,称为gawk。 在大多数Linux系统上,awk
解释器只是gawk
的符号链接。
记录和字段
Awk可以处理文本数据和流。 输入数据分为记录和字段。 Awk一次对一条记录进行操作,直到达到输入结束为止。 记录由称为记录分隔符的字符分隔。 默认的记录分隔符是换行符,这意味着文本数据中的每一行都是一条记录。 可以使用RS
变量来设置新的记录分隔符。
记录由字段分隔符分隔的字段组成。 默认情况下,字段之间用空格分隔,包括一个或多个制表符,空格和换行符。
每条记录中的字段均以美元符号($
)开头,后跟字段编号,从1开始。第一个字段由$1
表示,第二个字段由$2
表示,依此类推。 最后一个字段也可以用特殊变量$NF
引用。 整个记录可以用$0
。
以下是直观的图片,展示了如何引用记录和字段:
tmpfs 788M 1.8M 786M 1% /run/lock
/dev/sda1 234G 191G 31G 87% /
|-------| |--| |--| |--| |-| |--------|
$1 $2 $3 $4 $5 $6 ($NF) --> fields $1,$2...字段
|-----------------------------------------|
$0 --> record 多个字段组成的单行记录
Awk命令程序
要使用awk
处理文本,请编写一个程序来告诉命令该做什么。 该程序由一系列规则和用户定义的功能组成。 每个规则包含一个模式和一个动作。 规则用换行符或分号分隔(;
)。 通常,awk命令如下所示:
pattern { action }
pattern { action }
...
当awk
处理数据时,如果模式与记录匹配,则它将对该记录执行指定的操作。 当规则没有模式时,所有记录(行)都匹配。
awk action动作用花括号({}
)括起来,并由多个语句组成。 每个语句指定要执行的操作。 一个动作可以有多个语句,用换行符或分号隔开(;
)。 如果规则无效,则默认为打印整个记录。
Awk支持不同类型的语句,包括表达式,条件,输入,输出语句等。 最常见的awk语句是:
exit
-停止执行整个程序并退出。next
-停止处理当前记录,并移至输入数据中的下一个记录。print
-打印记录,字段,变量和自定义文本。printf
-使您可以更好地控制输出格式,类似于C和bashprintf
。
编写awk程序时,井号(#)
之后直至该行末的所有内容均被视为注释。 可以使用反斜杠(\
)将长行分成多行。
执行awk程序
awk程序可以通过多种方式运行。 如果程序简短而简单,则可以将其直接通过命令行传递给awk
解释器:
awk 'program' input-file...
在命令行上运行程序时,应将其括在单引号(''
)中,以便shell程序解释程序。
如果程序又大又复杂,最好将其放入文件中,并使用-f
选项将文件传递给awk
命令:
awk -f program-file input-file...
在以下示例中,我们将使用一个名为“ teams.txt”的文件,该文件如下所示:
Bucks Milwaukee 60 22 0.732
Raptors Toronto 58 24 0.707
76ers Philadelphia 51 31 0.622
Celtics Boston 49 33 0.598
Pacers Indiana 48 34 0.585
Awk模式
awk中的模式控制是否应执行关联的动作。
Awk支持不同类型的模式,包括正则表达式,关系表达式,范围和特殊表达式模式。
当规则没有模式时,将匹配每个输入记录。 这是仅包含操作的规则的示例:
awk '{ print $3 }' teams.txt
程序将打印每条记录的第三个字段:
60
58
51
49
48
正则表达式模式
正则表达式是与一组字符串匹配的模式。 Awk正则表达式模式包含在斜杠(//
)中:
/regex pattern/ { action }
最基本的示例是文字字符或字符串匹配。 例如,要显示每个包含“ 0.5”的记录的第一个字段,您可以运行以下命令:
awk '/0.5/ { print $1 }' teams.txt
Celtics
Pacers
模式可以是任何类型的扩展正则表达式。 这是一个示例,如果记录以两个或多个数字开头,则打印第一个字段:
awk '/^[0-9][0-9]/ { print $1 }' teams.txt
76ers
关系表达模式
关系表达式模式通常用于匹配特定字段或变量的内容。
默认情况下,正则表达式模式与记录匹配。 要将正则表达式与字段匹配,请指定该字段并针对模式使用“contain”包含比较运算符(~
)。
例如,要打印第二个字段包含“ ia”的每个记录的第一个字段,请输入:
awk '$2 ~ /ia/ { print $1 }' teams.txt
76ers
Pacers
要匹配不包含指定模式的字段,请使用!~
运算符:
awk '$2 !~ /ia/ { print $1 }' teams.txt
Bucks
Raptors
Celtics
您可以比较字符串或数字之间的关系,例如,大于,小于,等于等。 以下命令将打印第三字段大于50的所有记录的第一字段:
awk '$3 > 50 { print $1 }' teams.txt
Bucks
Raptors
76ers
范围模式
范围模式由用逗号分隔的两个模式组成:
pattern1, pattern2
从匹配第一个模式的记录开始的所有记录,直到匹配第二个模式的记录为止。
以下是一个示例,该示例将从包括“Raptors”的记录到包括“Celtics”的记录开始打印所有记录的第一个字段:
awk '/Raptors/,/Celtics/ { print $1 }' teams.txt
Raptors
76ers
Celtics
模式也可以是关系表达式。 下面的命令将打印所有记录,从第四个字段等于32的记录开始,直到第四个字段等于33的记录:
awk '$4 == 31, $4 == 33 { print $0 }' teams.txt
76ers Philadelphia 51 31 0.622
Celtics Boston 49 33 0.598
范围模式不能与其他模式表达式组合。
特殊表达模式
Awk包括以下特殊模式:
BEGIN
-用于在处理记录之前执行操作。END
-用于在处理记录后执行操作。
BEGIN
模式通常用于设置变量,END
模式通常用于处理记录中的数据,例如计算。
以下示例将打印“Start Processing.”,然后打印每个记录的第三个字段,最后打印“End Processing.”。
awk 'BEGIN { print "Start Processing." }; { print $3 }; END { print "End Processing." }' teams.txt
Start Processing
60
58
51
49
48
End Processing.
如果程序只有BEGIN
模式,则执行操作,并且不处理输入。 如果程序只有END
模式,则在执行规则操作之前先处理输入。
awk的Gnu版本还包括另外两个特殊模式BEGINFILE
和ENDFILE
,它们允许您在处理文件时执行操作。
组合模式
Awk允许您使用逻辑AND运算符(&&
)和逻辑OR运算符(||
)组合两个或多个模式。
这里是一个示例,该示例使用&&
运算符来打印第三字段大于50而第四字段小于30的那些记录的第一字段:
awk '$3 > 50 && $4 < 30 { print $1 }' teams.txt
Bucks
Raptors
内置变量
Awk具有许多内置变量,这些变量包含非常有用的信息,并允许您控制程序的处理方式。 以下是一些最常见的内置变量:
NF
-记录中的字段数。NR
-当前记录的编号。FILENAME
-当前正在处理的输入文件的名称。FS
-分隔符。RS
-记录分隔符。OFS
-输出字段分隔符。ORS
-输出记录分隔符。
以下是显示如何打印文件名和行数(记录)的示例:
awk 'END { print "File", FILENAME, "contains", NR, "lines." }' teams.txt
File teams.txt contains 5 lines.
AWK中的变量可以在程序的任何行中设置。 要为整个程序定义变量,请将其置于BEGIN
模式中。
更改字段和记录分隔符
字段分隔符的默认值为任意数量的空格或制表符。 可以通过在FS
变量中进行设置来更改。
例如,要将字段分隔符设置为.
,请使用:
awk 'BEGIN { FS = "." } { print $1 }' teams.txt
Bucks Milwaukee 60 22 0
Raptors Toronto 58 24 0
76ers Philadelphia 51 31 0
Celtics Boston 49 33 0
Pacers Indiana 48 34 0
字段分隔符也可以设置为多个字符:
awk 'BEGIN { FS = ".." } { print $1 }' teams.txt
在命令行上运行awk单行代码时,您还可以使用-F
选项更改字段分隔符:
awk -F "." '{ print $1 }' teams.txt
默认情况下,记录分隔符是换行符,可以使用RS
变量进行更改。
以下是显示如何将记录分隔符更改为.
的示例:
awk 'BEGIN { RS = "." } { print $1 }' teams.txt
Bucks Milwaukee 60 22 0
732
Raptors Toronto 58 24 0
707
76ers Philadelphia 51 31 0
622
Celtics Boston 49 33 0
598
Pacers Indiana 48 34 0
585
Awk action动作
Awk action动作括在大括号({}
)中,并在模式匹配时执行。 一个动作可以有零个或多个语句。 多个语句按照它们出现的顺序执行,并且必须用换行符或分号分隔(;
)。
awk支持几种类型的动作语句:
- 表达式,例如变量赋值,算术运算符,增量和减量运算符。
- 控制语句,用于控制程序的流程(
if
,for
,while
,switch
等) - 输出语句,例如
print
和printf
。 - 复合语句,可将其他语句分组。
- 输入语句 ,以控制输入的处理。
- Deletion语句,删除数组元素。
print
语句可能是最常用的awk语句。 它打印文本,记录,字段和变量的格式化输出。
打印多个项目时,需要用逗号分隔。 这是一个例子:
awk '{ print $1, $3, $5 }' teams.txt
打印的字段用单个空格分隔:
Bucks 60 0.732
Raptors 58 0.707
76ers 51 0.622
Celtics 49 0.598
Pacers 48 0.585
如果您不使用逗号,则字段之间将没有空格:
awk '{ print $1 $3 $5 }' teams.txt
这些字段是串联在一起的:
Bucks600.732
Raptors580.707
76ers510.622
Celtics490.598
Pacers480.585
如果不带参数使用print
,则默认为print $0
。 打印当前记录。
要打印自定义文本,必须用双引号引起来的文本:
awk '{ print "The first field:", $1}' teams.txt
The first field: Bucks
The first field: Raptors
The first field: 76ers
The first field: Celtics
The first field: Pacers
您还可以打印特殊字符,例如换行符:
awk 'BEGIN { print "First line\nSecond line\nThird line" }'
First line
Second line
Third line
printf
语句使您可以更好地控制输出格式。 这是一个插入行号的示例:
awk '{ printf "%3d. %s\n", NR, $0 }' teams.txt
printf
不会在每条记录后创建换行符,因此我们使用\n
:
1. Bucks Milwaukee 60 22 0.732
2. Raptors Toronto 58 24 0.707
3. 76ers Philadelphia 51 31 0.622
4. Celtics Boston 49 33 0.598
5. Pacers Indiana 48 34 0.585
以下命令计算每行第三字段中存储的值的总和:
awk '{ sum += $3 } END { printf "%d\n", sum }' teams.txt
266
这是另一个示例,显示了如何使用表达式和控制语句来打印从1到5的数字的平方:
awk 'BEGIN { i = 1; while (i < 6) { print "Square of", i, "is", i*i; ++i } }'
Square of 1 is 1
Square of 2 is 4
Square of 3 is 9
Square of 4 is 16
Square of 5 is 25
诸如上述的单行命令更难理解和维护。 在编写更长的程序时,您应该创建一个单独的程序文件:
prg.awk
BEGIN {
i = 1
while (i < 6) {
print "Square of", i, "is", i*i;
++i
}
}
通过将文件名传递给awk
解释器来运行程序:
awk -f prg.awk
您还可以通过使用 shebang 指令并设置awk
解释器,将awk程序作为可执行文件运行:
prg.awk
#!/usr/bin/awk -f
BEGIN {
i = 1
while (i < 6) {
print "Square of", i, "is", i*i;
++i
}
}
保存文件并使其可执行:
chmod +x prg.awk
您现在可以通过输入以下内容来运行程序:
./prg.awk
在Awk程序中使用Shell变量
如果您在Shell程序脚本中使用awk
命令,则很可能需要将Shell程序变量传递给awk程序。 一种选择是用双引号而不是单引号将程序引起来,并在程序中替换变量。 但是,此选项会使您的awk程序更加复杂,因为您需要对awk变量进行转义。
在awk程序中使用shell变量的推荐方法是将shell变量分配给awk变量。 这是一个例子:
num=51
51
结论
Awk是最强大的文本处理工具之一。
本文几乎没有触及awk编程语言的表面。 要了解有关awk的更多信息,请查看官方 Gawk文档。
如果您有任何问题或反馈,请随时发表评论。