专栏首页Opensource翻译专栏AWK中的字段,记录和变量【Programming】

AWK中的字段,记录和变量【Programming】

本文为awk入门系列的第二篇文章,在本篇文章中,你可以了解到有关字段,记录和一些功能强大的awk变量。

图片来源: Pixabay, CC0

Awk有很多变种:最初的awk于1977年在AT&T贝尔实验室诞生。在这之后有多种解释器,例如mawk ,nawk ,以及大多数Linux发行版,GNU awk或gawk附带的版本。在大多数Linux发行版中,awk和gawk是指代GNU awk的同义词,并且输入这其中任一命令都会调用相同的awk命令。如果想了解awk和gawk的历史版本和记录可以访问GNU awk用户指南

本系列的第一篇文章中展示了如何在命令行上调用awk,代码如下:

$ awk [options] 'pattern {action}' inputfile

awk是可包含参数(例如-F来定义字段分隔符)的命令,至少在终端中使用该命令时您可以在单引号中声明自己想要进行的操作。如果想要进一步强调awk命令中的哪一部分是您要执行的操作,可以选择在程序前加上-e选项(非必须):

$ awk -F, -e '{print $2;}' colours.txt
yellow
blue
green
[...]

记录和字段

Awk通常将其输入数据视为以换行符分隔的一系列记录。也就是说,awk通常会将文本文件中的每一行视为新记录。每个记录包含一系列字段。而记录由字段分隔符分割后则组成了字段。

默认设置下,awk将空白(例如空格,制表符和换行符)视为新字段的指示符。总的来说,awk将多个空格分隔符视为一个,因此此行包含两个字段:

raspberry red

下面这个例子也包含了两个字段:

tuxedo                  black

其他分隔符并不能通过这​​种方式处理。假如设定字段分隔符是逗号,下面的例子中将包含三个字段,其中一个字段的长度可能为零个字符(不可打印字符未隐藏在该字段中的情况下):

a,,b

AWK程序

awk命令的程序部分由一系列规则组成。通常,每个规则都在程序中的新行开始(尽管这并不是强制性的)。 每个规则都包含一个模式和多种操作:

pattern { action }

在规则中,可以将模式定义为条件,以控制是否对记录进行操作。模式可以是简单的比较,正则表达式,两者的组合等等。

例如,仅当包含单词“ raspberry”时,才打印记录:

$ awk '/raspberry/ { print $0 }' colours.txt
raspberry red 99

如果没有限定模式,那么该操作将应用于每个记录。此外,规则只能包含一个模式,例如当操作是{print}时,整条记录都将被写入。正因为操作取决于数据,awk程序本质上是数据驱动的,这与许多其他编程语言程序有很大的不同。

NF变量

每个字段都有一个变量作为名称,但是字段和记录也有特殊的变量。变量NF存储awk在当前记录中找到的字段数。可以打印或在测试中使用。下面是使用上一篇文章中的文本文件的示例:

$ awk '{ print $0 " (" NF ")" }' colours.txt
name       color  amount (3)
apple      red    4 (3)
banana     yellow 6 (3)
[...]

Awk的print函数采用一系列参数(变量或字符串)并将它们连接在一起。这就是awk在每一行末尾将字段数打印为用括号括起来的整数的原因。

NR变量

除了对每个记录中的字段进行计数外,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

printf()函数

使用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脚本

本文中的所有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以外的更多功能,请参考gawk手册

下面的例子希望能您能受到启发:

#!/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 }

使用此脚本来了解它的功能,然后尝试编写自己的脚本。

本系列的下一篇文章将介绍更多功能,用于更复杂也更有用的脚本。

本文改编自社区技术播客Hacker Public Radio

原文链接:https://opensource.com/article/19/11/fields-records-variables-awk

原文作者: Seth Kenlon (Red Hat)

我来说两句

0 条评论
登录 后参与评论

相关文章

  • Linux的虚拟机

    在工作中,经常需要在不同平台使用不同的软件,这时候虚拟机就是必需品了。在Linux上比较常见的有kvm、Xen、virtualbox、vmware workst...

    于小勇
  • Escape character is ‘^]’什么意思?怎么使用telnet

    在linux/unix下使用telnet(telnet ip 端口号)连接主机时提示“Escape character is '^]'.”,这是什么意思?“^”...

    ytkah
  • Oracle 12C 最新补丁下载与安装操作指北

    上一篇安装文档中说过 Oracle 也有一份安装手册,虽是英文版但很是详细,很有参考意义,如下是官方地址可查看详细内容:https://docs.oracle....

    JiekeXu之路
  • 【PCL入门系列之一】点云库PCL简介

    本系列文章首先介绍什么是PCL以及PCL的功能。之后将讲解如何在Linux上安装PCL,为下一步测试、编程、开发做准备。后续的文章将对PCL官网...

    小白学视觉
  • 面试题:如何理解 Linux 的零拷贝技术?

    本文讲解 Linux 的零拷贝技术,云计算是一门很庞大的技术学科,融合了很多技术,Linux 算是比较基础的技术,所以,学好 Linux 对于云计算的学习会有比...

    老钱
  • Linux 10个主流发行版本

    这里只表示做个记录。其实相关的介绍已经很多了。但是还是想怀缅一下青春。这10个Linux发行版来源于国外网站(最后给出链接)。它列出了10个Linux发行版(包...

    于小勇
  • Android Navigation的四大要点你都知道吗?

    在JetPack中有一个组件是Navigation,顾名思义它是一个页面导航组件,相对于其他的第三方导航,不同的是它是专门为Fragment的页面管理所设计的...

    Rouse
  • 为何killall有时找不到你的进程?killall是干什么的?

    在Linux下有很多命令用于杀死进程,它们可以用于不同的场景,例如通过进程名杀死进程,通过pid杀死进程。这些方法我不准备一一列举,本文想说明的一个问题是,为什...

    编程珠玑
  • linux下制作deb的方法总结

    deb是Unix系统(其实主要是Linux)下的安装包,基于 tar 包,因此本身会记录文件的权限(读/写/可执行)以及所有者/用户组。

    用户5807183
  • 入门学习SLAM(Windows &Ubuntu 16.04 双系统安装图片教程)

    入门学习SLAM计划是一个系列,从开始记录大家的学习过程,每一步我们都是有规划的。前一段时间发现了一篇安装Windows + Ubuntu 16.04 双系统安...

    小白学视觉

扫码关注云+社区

领取腾讯云代金券