本文介绍在Linux系统中使用Awk命令的示例,及掌握Awk编程语言的基本知识,这将大大提高您在命令行上操作文本文件的能力。Awk是一种用于高级文本处理的通用脚本语言,它主要用作报告和分析工具。与大多数其他程序性编程语言不同,Awk是数据驱动的,这意味着您定义了一组针对输入文本要执行的操作,它获取输入数据,对其进行转换,然后将结果发送到标准输出。可参考在Fedora系统下使用Awk的方法。
awk如何运作 awk有几种不同的实现,我们将使用awk的GNU实现,称为gawk,在大多数Linux系统上,awk解释器只是与gawk的符号链接。 1、记录和字段 Awk处理来自文件或流的文本数据,输入数据分为记录和字段,Awk一次对一条记录进行操作,直到达到输入结束为止。记录由称为记录分隔符的字符分隔,默认的记录分隔符是换行符,这意味着文本数据中的每一行都是一条记录,可以使用RS变量设置新的记录分隔符。 记录包含由字段分隔符分隔的字段,默认情况下,字段之间用空格分隔,包括一个或多个制表符、空格和换行符。 每个记录中的字段均以美元符号($)开头,后跟字段编号,以1开头。第一个字段以$1表示,第二个字段以$2表示,依此类推,最后一个字段也可以用特殊变量$NF引用,整个记录可以用$0引用。 这是显示如何引用记录和字段的直观表示:
2、AWK程序 要使用awk处理文本,您需要编写一个程序来告诉命令该做什么,该程序由一系列规则和用户定义的功能组成,每个规则包含一个模式和一个动作对,规则以换行符或分号(;)分隔,通常,awk程序如下所示: pattern { action } pattern { action } ... 当awk处理数据时,如果模式与记录匹配,它将在该记录上执行指定的操作,当规则没有模式时,将匹配所有记录(lines)。 awk操作用大括号({})括起来,并由多个语句组成,每个语句指定要执行的操作,一个动作可以有多个语句,用换行符或分号(;)分隔,如果规则不起作用,则默认为打印整个记录。 Awk支持不同类型的语句,包括表达式、条件、输入、输出语句等,最常见的awk语句是: exit-停止执行整个程序并退出。 next-停止处理当前记录,并移至输入数据中的下一个记录。 print-打印记录、字段、变量和自定义文本。 printf-使您可以更好地控制输出格式,类似于C和bash printf。 编写awk程序时,井号(#)之后直到该行末尾的所有内容均被视为注释,可以使用连字符反斜杠(\)将长行分成多行。 3、执行awk程序 awk程序可以通过多种方式运行,如果程序简短而简单,则可以将其直接通过命令行传递给awk解释器: awk 'program' input-file... 在命令行上运行程序时,应将其括在单引号('')中,以便Shell程序不解释程序。 如果程序又大又复杂,则最好将其放在文件中,并使用-f选项将文件传递给awk命令: awk -f program-file input-file... 在下面的示例中,我们将使用一个名为“teams.txt”的文件,该文件如下所示:
Awk模式 awk中的模式控制是否应该执行关联的动作。 Awk支持不同类型的模式,包括正则表达式、关系表达式、范围和特殊表达式模式。 当规则没有模式时,将匹配每个输入记录,这是仅包含操作的规则的示例: awk '{ print $3 }' teams.txt 该程序将打印每个记录的第三个字段: 60 58 51 49 48 1、正则表达式模式 正则表达式或正则表达式是与一组字符串匹配的模式,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 2、关系表达模式 关系表达式模式通常用于匹配特定字段或变量的内容。 默认情况下,正则表达式模式与记录匹配,要将正则表达式与字段进行匹配,请指定该字段,然后对模式使用“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 3、范围模式 范围模式由用逗号分隔的两个模式组成: 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 返回:
范围模式不能与其他模式表达式结合使用。 4、特殊表达方式 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模式,则在执行规则操作之前先处理输入。 GNU版本的awk还包括另外两个特殊模式BEGINFILE和ENDFILE,它们使您可以在处理文件时执行操作。 5、组合模式 Awk允许您使用逻辑AND运算符(&&)和逻辑OR运算符(||)组合两个或多个模式。 这是一个使用&&运算符来打印第三字段大于50而第四字段小于30的记录的第一字段的示例: awk '$3 > 50 && $4 < 30 { print $1 }' teams.txt 返回:
内置变量 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 返回:
字段分隔符也可以设置为多个字符: awk 'BEGIN { FS = ".." } { print $1 }' teams.txt 在命令行上运行awk单线时,还可以使用-F选项来更改字段分隔符: awk -F "." '{ print $1 }' teams.txt 默认情况下,记录分隔符是换行符,可以使用RS变量进行更改。 这是显示如何将记录分隔符更改为.的示例: awk 'BEGIN { RS = "." } { print $1 }' teams.txt 返回:
Awk动作 Awk操作用大括号({})括起来,并在模式匹配时执行,一个动作可以有零个或多个语句,多个语句按照它们出现的顺序执行,并且必须用换行符或分号(;)分隔。 awk支持多种类型的动作语句: 表达式,例如变量赋值、算术运算符、递增和递减运算符。 控制语句,用于控制程序的流程(if、for、while、switch和more)。 输出语句,例如print和printf。 复合语句,将其他语句分组。 输入语句,以控制输入的处理。 删除语句,删除数组元素。 打印语句可能是最常用的awk语句,它打印文本、记录、字段和变量的格式化输出。 打印多个项目时,需要用逗号分隔,这是一个例子: awk '{ print $1, $3, $5 }' teams.txt 打印的项目由单个空格分隔:
如果您不使用逗号,则项目之间将没有空格: awk '{ print $1 $3 $5 }' teams.txt 这些项目是串联的:
当使用不带参数的print时,默认情况下打印$0,当前记录被打印。 要打印自定义文本,必须用双引号引起来的文本: awk '{ print "The first field:", $1}' teams.txt 返回:
您还可以打印特殊字符,例如换行符: awk 'BEGIN { print "First line\nSecond line\nThird line" }' 返回:
printf语句使您可以更好地控制输出格式,这是一个插入行号的示例: awk '{ printf "%3d. %s\n", NR, $0 }' teams.txt printf不会在每条记录之后创建换行符,因此我们使用\n:
以下命令计算每行第三字段中存储的值的总和: 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 } }' 返回:
单行命令(如上面的命令)较难理解和维护,编写更长的程序时,应创建一个单独的程序文件,名称prg.awk: prg.awk BEGIN { i = 1 while (i < 6) { print "Square of", i, "is", i*i; ++i } } 通过将文件名传递给awk解释器来运行程序: awk -f prg.awk 您还可以通过使用shebang指令并设置awk解释器将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 awk -v n="$num" 'BEGIN {print n}' 返回: 51
结语 Awk是用于文本操作的最强大的工具之一,以上示例的Awk命令使用也是较为基础的。 本文介绍的Awk编程语言基本知识对于您来说非常有用,因为掌握这些对于进阶Awk非常有好处,也是必不可少的。
相关主题 |