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