本文共 5131 字,大约阅读时间需要 17 分钟。
awk命令取字段用变量
Awk有多种变体:有原始的awk ,写于1977年在AT&T贝尔实验室,还有一些重新实现,例如mawk , nawk ,以及大多数Linux发行版,GNU awk或gawk附带的版本。 在大多数Linux发行版中,awk和gawk是指代GNU awk的同义词,并且键入任何一个都会调用相同的awk命令。 有关awk和gawk的完整历史记录,请参见 。
本系列的表明,使用以下语法在命令行上调用awk:
$ awk [ options ] 'pattern {action}' inputfile
Awk是命令,它可以使用选项(例如-F来定义字段分隔符)。 您希望awk执行的操作包含在单引号中,至少在终端中发出时。 为了进一步强调awk命令的哪一部分是您要执行的操作,可以在程序前加上-e选项(但不是必需的):
$ awk -F, -e '{print $2;}' colours.txt yellow blue green [ ... ]
默认情况下,awk会将空白(例如空格,制表符和换行符)视为新字段的指示符。 具体来说,awk将多个空格分隔符视为一个,因此此行包含两个字段:
raspberry red
与此一样:
tuxedo black
其他分隔符未采用这种方式处理。 假定字段分隔符是逗号,下面的示例记录包含三个字段,其中一个字段的长度可能为零个字符(假定不可打印字符未隐藏在该字段中):
a,,b
awk命令的程序部分由一系列规则组成。 通常,每个规则都在程序中的新行开始(尽管这不是强制性的)。 每个规则都包含一个模式和一个或多个操作:
pattern { action }
在规则中,您可以将模式定义为条件,以控制操作是否将在记录上运行。 模式可以是简单的比较,正则表达式,两者的组合等等。
例如, 仅当包含单词“ raspberry”时, 才打印记录:
$ awk '/raspberry/ { print $0 }' colours.txt raspberry red 99
如果没有限定模式,则该操作将应用于每个记录。
另外,规则只能包含一个模式,在这种情况下,整个记录都将被写入,就好像操作是{print}一样 。
Awk程序本质上是数据驱动的 ,因为操作取决于数据,因此它们与许多其他编程语言中的程序有很大的不同。
每个字段都有一个变量作为名称,但是字段和记录也有特殊的变量。 变量NF存储awk在当前记录中找到的字段数。 可以打印或在测试中使用。 这是使用上一篇文章的的示例:
$ awk '{ print $0 " (" NF ")" }' colours.txt name color amount ( 3 ) apple red 4 ( 3 ) banana yellow 6 ( 3 ) [ ... ]
Awk的print函数采用一系列参数(可以是变量或字符串)并将它们连接在一起。 这就是为什么在此示例中,在每行的末尾,awk将字段数打印为用括号括起来的整数。
除了对每个记录中的字段进行计数外,awk还对输入记录进行计数。 记录号保存在变量NR中 ,并且可以与任何其他变量相同的方式使用。 例如,要在每行之前打印记录号:
$ awk '{ print NR ": " $0 }' colours.txt 1 : name color amount 2 : apple red 4 3 : banana yellow 6 4 : raspberry red 3 5 : grape purple 10 [ ... ]
请注意,可以使用以下命令编写此命令,除了打印后的空格外,其他任何空格都是可以接受的,尽管对于人类而言,解析起来更加困难:
$ awk '{print NR": "$0}' colours.txt
为了更灵活地格式化输出,可以使用awk printf()函数。 这类似于使用C,Lua,Bash和其他语言的printf 。 它采用格式参数,后跟逗号分隔的项目列表。 参数列表可以用括号括起来。
$ printf format, item1, item2, ...
format参数(或format string )定义了如何输出其他每个参数。 它使用格式说明符来执行此操作,其中包括%s输出字符串和%d输出十进制数。 以下printf语句输出记录,后跟括号中的字段数:
$ awk 'printf "%s (%d)\n",$0,NF}' colours.txt name color amount ( 3 ) raspberry red 4 ( 3 ) banana yellow 6 ( 3 ) [ ... ]
在此示例中, %s(%d)提供了每一行的结构,而$ 0,NF定义了要插入到%s和%d位置的数据。 请注意,与打印功能不同,没有显式指令就不会生成换行符。 转义序列\ n执行此操作。
本文中的所有awk代码均已在交互式Bash提示符下编写并执行。 对于更复杂的程序,将命令放入文件或脚本通常更容易。 选项-f FILE (不要与-F混淆,它表示字段分隔符)可用于调用包含程序的文件。
例如,这是一个简单的awk脚本。 使用以下内容创建一个名为example1.awk的文件:
/ ^a / { print "A: " $0 } / ^b / { print "B: " $0 }
通常给此类文件扩展名.awk ,以明确表明它们包含awk程序。 这种命名不是强制性的,但它为文件管理器和编辑器(以及您)提供了有关文件内容的有用线索。
运行脚本:
$ awk -f example1.awk colours.txt A: raspberry red 4 B: banana yellow 6 A: apple green 8
可以通过添加#!将包含awk指令的文件制成脚本。 行顶部,使其可执行。 使用以下内容创建一个名为example2.awk的文件:
#!/usr/bin/awk -f # # Print all but line 1 with the line number on the front # NR > 1 { printf "%d: %s \n " ,NR, $0 }
可以说,在脚本中只包含一行是没有优势的,但是有时执行脚本比记住并键入一行要容易得多。 脚本文件还提供了很好的机会来记录命令的作用。 以#符号开头的行是注释,awk会忽略它们。
授予文件可执行权限:
$ chmod u+x example2.awk
运行脚本:
$ . / example2.awk colours.txt 2 : apple red 4 2 : banana yellow 6 4 : raspberry red 3 5 : grape purple 10 [ ... ]
将awk指令放置在脚本文件中的一个优点是格式和编辑更加容易。 虽然您可以在终端机的一行中编写awk,但当它跨越多行时可能会变得不知所措。
现在,您对awk如何处理您的指令以编写一个复杂的awk程序了如指掌。 尝试编写具有多个规则和至少一个条件模式的awk脚本。 如果您想尝试除print和printf以外的更多功能,请在线参考 。
这是一个让您入门的想法:
#!/usr/bin/awk -f # # Print each record EXCEPT # IF the first record contains "raspberry", # THEN replace "red" with "pi" $1 == "raspberry" { gsub ( / red / , "pi" ) } { print }
尝试使用此脚本查看其功能,然后尝试编写自己的脚本。
本系列的下一篇文章将介绍更多功能,用于更复杂(更有用!)的脚本。
本文改编自社区技术播客 。
翻译自:
awk命令取字段用变量
转载地址:http://mpszd.baihongyu.com/