gawk

转GAWK 入门:AWK 语言基础

利用 GAWK 的开放源代码实现学习 AWK

了解 AWK 文本处理和模式扫描语言的基本概念。本教程将带您开始使用 AWK 进行编程:您将了解 AWK 如何读取输入数据和对其进行排序、如何运行 AWK 程序、操作数据并进行复杂的模式匹配。当您完成本教程的学习时,同时也了解了 GNU AWK (GAWK)。

Michael Stutz (stutz@dsl.org), 作家, 顾问

2006 年 11 月 02 日

  • expand内容

开始之前

了解本教程中介绍的内容、如何最好地利用它以及在学习本教程的过程中需要完成哪些工作。

关于本教程

GNU AWK (GAWK) 是历史悠久的 AWK 编程语言的开放源代码实现,可用于所有的 UNIX® 系统。AWK 语言是一种 UNIX 备用工具,它是一种功能强大的文本操作和模式匹配语言,特别适用于进行信息检索,这使得它非常适合用于当今的数据库驱动的应用程序。因为它集成于 UNIX 环境,所以可以设计、构建和快速地执行完整的工作程序,并且立即就能得到结果。

本教程为 AWK 文本处理语言提供了实践性的介绍。它介绍了如何使用开放源代码 GAWK 解释器来编写和执行 AWK 程序,以便通过各种方式来搜索和操作数据。

目标

本教程面向那些需要利用 AWK 强大的文本操作功能的读者。在本教程中,您将使用 GAWK,以了解各种运行 AWK 程序的方法。您还将了解如何组织程序,并学习 AWK 的记录和字段范例。在完成本教程后,您可以学习到该语言的基本内容,包括格式化输出、记录和字段操作以及模式匹配。您还应该能够编写自定义的 AWK 程序,以使用 UNIX 命令行执行复杂的文本处理。

先决条件

本教程没有特殊的先决条件,不过您应该熟悉 UNIX 命令行 Shell 的使用。如果您对 C 编程语言的构造比较熟悉,那么将会很有帮助,但这并不是必需的。

系统要求

您必须在系统中安装 GAWK 的工作副本,最好是 Version 3.0 或更高版本。很容易获得 GAWK 的源代码和二进制包(请参见参考资料部分)。如果您使用源代码安装 GAWK,请参考 GAWK 源代码分发版中的 README 文件,其中列出了进行成功的编译和安装所需的任何附加软件。

准备好开始使用 GAWK

了解 AWK 编程语言以及不同实现之间的差异,并准备好安装 GAWK,以便可以开始进行编程。

AWK 语言

AWK 是该编程语言本身的名称,它编写于 1977 年。其名称是三个主要作者的姓的首字母缩写:Drs. A. Aho、P. Weinberger 和 B. Kernighan。

因为 AWK 是一种文本处理和模式匹配语言,所以它通常称为数据驱动的 语言,程序语句描述需要进行匹配和处理的输入数据,而不是程序操作步骤的序列,在许多语言中都是这样的。AWK 程序在其输入数据中搜索包含模式的记录、对该记录执行指定的操作,直到程序到达输入的末尾。AWK 程序擅长于处理数据库和表型数据,如从多个数据集中提取一些列、建立报表或分析数据。事实上,AWK 适合于编写短小的、一次性程序,以执行一些灵活的文本处理,而使用其他的语言则可能成本较高。另外,作为一种功能强大的工具,AWK 常常在命令行中使用或与管道一起使用。

与 Perl(它起源于 AWK)一样,AWK 是一种解释性语言,所以 AWK 程序通常不需要进行编译。相反,在运行时将程序脚本传递给 AWK 解释器。

AWK 输入语言使用类似 C 语言的语法,这使得系统编程人员感觉到非常的方便。事实上,其中许多特性,包括控制语句和字符串函数,如 printfsprintf,基本上是相同的。然而,也存在着一些差异。

AWK 的不同版本

在 20 世纪 80 年代中期,对 AWK 语言进行了更新,并不同程度地使用一种称为 NAWK (New AWK) 的增强版本对其进行了替换。许多系统中仍然存在着旧的 AWK 解释器,但通常将其安装为 oawk (Old AWK) 命令,而 NAWK 解释器则安装为主要的 awk 命令,也可以使用 nawk 命令。Dr. Kernighan 仍然在对 NAWK 进行维护,与 GAWK 一样,它也是开放源代码的,并且可以免费获得(请参见参考资料部分)。

GAWK 是 GNU Project 的 AWK 解释器的开放源代码实现。尽管早期的 GAWK 发行版是旧的 AWK 的替代程序,但不断地对其进行了更新,以包含 NAWK 的特性。

在本教程中,AWK 始终表示引用通用的语言,而 GAWK 或 NAWK 实现所特有的特性则使用它们的名称进行引用。您可以在参考资料部分中找到关于 GAWK、NAWK 和其他重要的 AWK 站点的链接。

GAWK 的特性和优点

GAWK 具有下列独特的特性和优点:

  • 在所有主要的 UNIX 平台以及其他操作系统中都可以使用它,包括 Mac OS X 和 Microsoft® Windows®。
  • 它是可移植操作系统接口 (POSIX) 兼容的,并且包含 1992 POSIX 标准中的所有特性。
  • 它没有预定义的内存限制。
  • 可以使用一些新的内置函数和变量。
  • 它包含一些特殊的 regexp 操作符。
  • 记录分隔符中可以包含 regexp 操作符。
  • 可以使用特殊文件支持来访问标准的 UNIX 流。
  • 可以使用 Lint 检查。
  • 在缺省情况下,它使用扩展的正则表达式。
  • 它支持无限制的行长度和连续使用反斜杠字符 (\)。
  • 它具有更好的、更具描述性的错误消息。
  • 它包含一些 TCP/IP 网络函数。

检查版本

在安装了 GAWK 之后,首先您必须确定本地副本放在什么地方。大多数系统使用 GAWK 作为它们主要的 AWK 安装,比如将 /usr/bin/awk 作为 /usr/bin/gawk 的符号链接,这样一来,awk 就成了 GAWK 解释器命令的名称。本教程采取了这种安装方式。在有些系统中,已经安装了其他版本的 AWK 或者具有高优先级,那么您可能需要使用 gawk 来调用 GAWK。

如果输入 awk 命令并得到 GNU 使用方法屏幕,如清单 1 所示,那么您将了解到是否正确地安装了所有的内容。大多数版本的 AWK 不会返回任何内容。

清单 1. 将 GAWK 安装为 awk
$ awk
Usage: gawk [POSIX or GNU style options] -f progfile [--] file ...
Usage: gawk [POSIX or GNU style options] [--] 'program' file ...
POSIX options:          GNU long options:
        -f progfile             --file=progfile
        -F fs                   --field-separator=fs
        -v var=val              --assign=var=val
        -m[fr] val
        -W compat               --compat
        -W copyleft             --copyleft
        -W copyright            --copyright
        -W dump-variables[=file]        --dump-variables[=file]
        -W gen-po               --gen-po
        -W help                 --help
        -W lint[=fatal]         --lint[=fatal]
        -W lint-old             --lint-old
        -W non-decimal-data     --non-decimal-data
        -W profile[=file]       --profile[=file]
        -W posix                --posix
        -W re-interval          --re-interval
        -W source=program-text  --source=program-text
        -W traditional          --traditional
        -W usage                --usage
        -W version              --version

To report bugs, see node `Bugs' in `gawk.info', which is
section `Reporting Problems and Bugs' in the printed version.

正如您所看到的,GAWK 接受 GNU 的标准选项,以获得版本信息。所得到的输出,包括自由软件基金会关于 GAWK 的许可和缺少担保的公告,它应该与清单 2 所示类似。

清单 2. 显示 GAWK 的版本
$ gawk --version
GNU Awk 3.1.5
Copyright (C) 1989, 1991-2005 Free Software Foundation.

This program is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation; either version 2 of the License, or
(at your option) any later version.

This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.

You should have received a copy of the GNU General Public License
along with this program; if not, write to the Free Software
Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
$

现在您已经安装了 GAWK,并且知道如何调用它,那么就可以开始进行编程了。下一部分将描述基本的 AWK 编程概念。

了解记录、字段和规则

了解 AWK 编程语言的基础知识:记录、字段和规则。

AWK 输入文件的组成部分

AWK 针对文本输入进行操作,而该文本可以是一个文件或标准输入流,它对文本进行分类以得到记录和字段。AWK 记录 是单个的、连续长度的输入数据,是 AWK 的操作对象。记录由记录分隔符 限定,记录分隔符是一个字符串,并且定义为 RS 变量(请参见更改记录分隔符部分)。在缺省情况下,RS 的值设置为换行符,所以 AWK 的缺省行为是将整行输入作为记录。

连续地读取记录,直到到达输入的末尾。图 1 显示了如何将输入数据分解为记录。

图 1. 将 AWK 输入数据划分为记录

将 AWK 输入数据划分为记录

还可以将每个记录进一步分解为称作字段 的单独的块。与记录一样,字段也受到限定。缺省的字段分隔符 是任意数量的空白字符,包括制表符和空格字符。所以在缺省情况下,将输入行进一步分解为单独的单词(由空白字符分隔的任何字符组)。

您可以通过字段编号来引用记录中的字段,从 1 开始。您可以使用字段编号或特殊的变量 NF 来调用每个记录中的最后一个字段,该变量包含当前记录中字段的个数。

您可以通过字段编号 0 来引用整个记录,包括所有的字段和字段分隔符。图 2 显示了这样一个字段的内容,即将 AWK 输入数据的单个记录分解为复合字段。

图 2. AWK 记录中的字段

AWK 记录中的字段

注意:AWK 提供了许多方式将字段中的组成部分划分为其字符组成部分,但这超出了本教程的讨论范围。

了解规则

AWK 程序由规则 组成,它们是一些模式,后面跟着由换行分隔的操作。当 AWK 执行一条规则时,它在输入记录中搜索给定模式的匹配项,然后对这些记录执行给定的操作:

/pattern/ { action }

您可以在规则中省略模式或操作。

操作由 AWK 语句组成,使用分号 (;) 来进行分隔。您还可以在同一行内容中提供多个规则,但是您必须使用分号对它们进行分隔。当规则中仅包含一项操作时,将对输入中的每条记录执行该操作。当规则中仅包含一个模式时,将打印出匹配该模式的所有记录。

空模式 // 匹配空字符,这等价于规则中不包含任何模式。然而,当给定空操作 {} 时,这并不等价于没有任何操作。空操作表示不进行任何操作(因此,不打印出该记录)。

打印输入中的每个记录

您可以编写一条规则,以不同的方式打印出输入中的每个记录,最简单的方法如下所示:

//

这等价于:

{ print }

正规的方法是:

// { print }

这可能是 AWK 中最简单的程序。尽管它没有完成任何惊人的操作,但使用并不比这大多少的程序,就可以执行非常复杂的操作。

使用 BEGIN 和 END 模式

AWK 包含两种特殊的模式:BEGINEND。它们都不需要使用斜线。BEGIN 模式指定了在处理任何记录之前需要执行的操作:

BEGIN {action}

END 模式指定在处理了所有记录之后需要执行的操作:

END {action}

BEGIN 通常用来设置变量,而 END 通常用来对从输入记录中读取的数据和图表进行制表、汇总和处理。通常,这些模式可以用来在输出经过处理的文本之前和之后输出文本。

例如,您可以在程序开始和结束之前输出一些消息,如清单 3 中的 AWK 程序所示。

清单 3. 带 BEGIN 和 END 模式的程序
# Program to print a file with a header and footer.

BEGIN { print "Beginning of file";
    print "-----------------" }

// # Print every line in the file.

END { print "------------";
      print "End of file."}

请注意,这些语句由分号分隔,并且该程序的注释以井号开头。

一些基本的操作

通常,您可以使用 AWK 语言语句来构建操作,如清单 3 中的 print 语句。表 1 列出了操作中的一些最常用的 GAWK 语句和函数,并对它们的含义进行了描述。对于 C 编程人员,请注意 C 语言的语句和函数与 AWK 对等部分之间的相似之处。

表 1. 常用的 GAWK 语句
语句描述
exit 停止程序的执行,并且退出。
next 停止处理当前记录,并且前进到下一条记录。
nextfile 停止处理当前文件,并且前进到下一个文件。
print 打印使用引号括起来的文本、记录、字段和变量。(缺省情况下是打印出当前整行记录。)
printf 打印格式化文本,类似于它的 C 语言对等成分,但必须指定结尾的换行。
sprintf 返回格式化文本字符串,与 printf 使用相同的格式。

运行 GAWK 程序

GAWK 接受两个输入文件,即包含 AWK 程序本身的命令文件和要进行处理的数据文件。您需要一些示例数据,所以可以使用文本编辑器向名为 sample 的文件加入清单 4 中所有的内容(三行内容)。

清单 4. 示例文本
Heigh-ho! sing, heigh-ho! unto the green holly:
Most friendship is feigning, most loving mere folly:
Then, heigh-ho, the holly!

运行 GAWK 程序的不同方法

您可以使用四种方法来运行 GAWK 程序:在命令行中、作为筛选器、从文件或作为脚本。

在命令行中

不需要将命令保存到文件中:您可以将它们作为参数传递。这是运行 GAWK 单行程序 的常用方法。

其格式是:

awk 'program' filespec

尝试使用下面的单行程序,以打印出示例文件中的每行内容:

$ awk '{ print }' sample
Heigh-ho! sing, heigh-ho! unto the green holly:
Most friendship is feigning, most loving mere folly:
Then, heigh-ho, the holly!
$

这个程序读取示例文件,并打印出其中的每个记录,换句话说,它仅仅逐字地输出整个文件。对于 GAWK,该文件中的数据与图 3 所示类似。

图 3. GAWK 对示例文件的解释

GAWK 对示例文件的解释

因为 GAWK 可以接受多个输入文件,所以如果您指定多个输入文件作为参数,该程序可以将它们连接起来。

单行程序并不仅限于一行中的程序。例如,您可以在命令行中使用引号将清单 3 中的所有内容括起来,该程序将运行清单 5 中的代码。

清单 5. 多行内容的单行程序
$ awk 'BEGIN { print "Beginning of file.";
print "------------------" },
//
END { print "------------";
print "End of file."}' sample
Beginning of file
-----------------
Heigh-ho! sing, heigh-ho! unto the green holly:
Most friendship is feigning, most loving mere folly:
Then, heigh-ho, the holly!
------------
End of file.
$

除了任意长度输入程序的实用性之外,在命令行中运行 AWK 程序需要注意一点:必须小心地使用引号!AWK 中的变量,如 $1,可以表示字段,这一点将在下一个部分中进行描述,在许多 Shell 中,这些字段是特殊的变量,而这些变量将转换为在命令行中给定的参数。

作为筛选器

AWK 通常用作管道中的文本筛选器。在这种情况下,GAWK 从标准输入读取数据:

awk 'program'

尝试使用示例文件测试下面的命令:

$ cat sample | awk '{ print }'
Heigh-ho! sing, heigh-ho! unto the green holly:
Most friendship is feigning, most loving mere folly:
Then, heigh-ho, the holly!
$

来自文件

在实际中,通常只在命令行中运行单行程序。大型的 GAWK 程序通常保存在文件中。可以使用 -f 选项指定程序文件。

所以,假设一个名为 progfile 的文件中包含下面的内容:

{ print }

当您运行下面的命令时,将与在在命令行中运行 awk 得到相同的结果:

$ awk -f progfile sample
Heigh-ho! sing, heigh-ho! unto the green holly:
Most friendship is feigning, most loving mere folly:
Then, heigh-ho, the holly!
$

请注意,如果程序放在文件中,那么就不需要在 Shell中使用引号将内容括起来。

作为脚本

另一种运行 GAWK 程序的方法是将其放到文件中,并使用 shebang 命令(井号加感叹号)将该文件变成可执行的脚本,如果您的 Shell 支持这种方法。

将程序放到一个名为 awkat 的 GAWK 脚本文件中,使其具有执行权限,并尝试使用示例文件运行该脚本,如清单 6 中所示。

清单 6. 将简单的程序作为可执行文件运行
$ cat > awkat#!/usr/bin/awk -f{ print }Ctrl-d
$ chmod u+x awkat
$ ./awkat sample
Heigh-ho! sing, heigh-ho! unto the green holly:
Most friendship is feigning, most loving mere folly:
Then, heigh-ho, the holly!
$

操作记录和字段

当 GAWK 读入一个记录时,它会将该记录中所有的字段存储到变量中。您可以通过使用 $ 加上字段编号来引用每个字段,所以 $1 引用第 1 个字段,$2 引用第 2 个字段,依此类推,直到记录中的最后一个字段。

图 4 以缺省的记录和字段显示了示例文本。

图 4. 将示例文件分解为 AWK 记录和字段

将示例文件分解为 AWK 记录和字段

输入文件的组成部分中所述,您可以使用 $0 来引用整个记录,其中包括所有的字段和字段分隔符。这是许多命令的缺省值。所以例如,正如前面使用过的 print,它等价于 print $0,这两个命令都将打印出当前整个记录。

打印特定的字段

要输出某个特定的字段,可以将该字段的名称作为参数提供给 print。下面的命令尝试打印示例文件中每个记录的第 1 个字段:

$ awk ' { print $1 } ' sample
Heigh-ho!
Most
Then,
$

您可以在 print 语句中提供多个字段,并且它们可以使用任意的顺序:

$ awk ' { print $7, $3, $1 } ' sample
holly: heigh-ho! Heigh-ho!
mere is Most
 the Then,
$

请注意,有些行中没有第 7 个字段,在这种情况下,将不打印任何内容。

当使用逗号进行分隔时,这些字段在输出时将使用空格隔开。您可以省略逗号,以便将它们连接起来。要打印第 7 个和第 8 个字段,并将它们连接起来,可以使用下面的命令:

$ awk ' { print $7 $8 } ' sample
holly:
merefolly:
$

您可以将使用引号括起来的文本和字段组合在一起。尝试下面的命令:

$ awk ' { print "Field 2: " $2 } ' sample
Field 2: sing,
Field 2: friendship
Field 2: heigh-ho,
$

您已经了解了处理字段和记录的强大功能,使用 AWK,很容易对表型数据进行解析、操作,并使用一些简单的命令重新进行格式化。您可以使用 Shell 重定向机制将经过重新格式化的输出定向到一个新的文件,或使用管道进行传输。

如果作为筛选器使用,那么可以将这种功能与其他的命令联合使用,这是非常有价值的。例如,下面的命令修改了日期的缺省输出,以便以日 月,年 的格式进行输出:

$ date|awk '{print $3 " " $2 ", " $6}'
29 Nov, 2006
$

更改字段分隔符

到目前为止,示例中的字段都使用空格字符进行分隔。这是缺省的行为,即任意个数的空格或制表符,您可以对其进行更改。字段分隔符的值保存在 FS 变量中。与 AWK 中的其他变量一样,可以在程序中的任何位置对其进行重新定义。要对整个文件使用不同的字段分隔符,可以在 BEGIN 语句重新定义它。

使用感叹号 (!) 作为字段分隔符打印示例数据的第 1 个字段:

$ awk ' BEGIN { FS = "!" } { print $1 } ' sample
Heigh-ho
Most friendship is feigning, most loving mere folly:
Then, heigh-ho, the holly
$

请注意在打印第 2 个和第 3 个字段时的差别:

$ awk ' BEGIN { FS = "!" } { print $2 } ' sample
 sing, heigh-ho


$ awk ' BEGIN { FS = "!" } { print $3 } ' sample
 unto the green holly:


$

尝试将输出中的字段与图 4 中列出的字段进行比较。

但是字段分隔符并不一定必须是单个字符。可以使用一个短语:

$ awk ' BEGIN { FS = "Heigh-ho" } { print $2 } ' sample
! sing, heigh-ho! unto the green holly:


$

在 GAWK 中,字段分隔符可以是任何正则表达式。要使每个输入字符成为一个独立的字段,可以让 FS 的值为空。

算出大写字母的总数。上面的示例仅在整个文件中匹配一个分隔符,而下面的示例将匹配短语,无论大小写:

$ awk ' BEGIN { FS = "[Hh]eigh-ho" } { print $2 } ' sample
! sing, 

, the holly!
$

通过在命令行中使用引号将其括起来并作为 -F 选项的参数,也可以更改字段分隔符:

$ awk -F "," ' { print $2 } ' sample
 heigh-ho! unto the green holly:
 most loving mere folly:
 heigh-ho
$

使用这种功能,很容易创建可以对文件进行解析的单行程序,如 /etc/passwd,其中的字段由冒号 (:) 进行分隔。您可以轻松地从中提取完整的用户名称列表,例如:

$ awk -F ":" ' { print $5 } ' /etc/passwd

更改记录分隔符

与字段分隔符一样,您可以将记录分隔符的缺省值(换行符)更改为所需的任何内容。其当前值保存在 RS 变量中。

将记录分隔符更改为逗号,并对示例文件使用它:

$ awk ' BEGIN { RS = "," } //' sample
Heigh-ho! sing
 heigh-ho! unto the green holly:
Most friendship is feigning
 most loving mere folly:
Then
 heigh-ho
 the holly!
$

更改输出

对 AWK 输出的处理与 AWK 输入数据一样,它被分解为许多字段和记录,输出流具有自己的分隔符,初始情况下与输入分隔符的缺省值相同,即空格和换行。print 语句中的字段由逗号分隔,该语句中使用的输出字段分隔符 设置为单个空格,您可以重新定义 OFS 变量,以对其进行更改。输出记录分隔符 设置为换行符,您可以通过重新定义 ORS 变量对其进行更改。

要从文件中删除所有的换行,并将文件中所有的文本置于一行,只需将输出记录分隔符更改为空字符即可,对于某些文本分析和筛选来说,这样做是非常有价值的。

使用示例文件尝试下面的命令:

$ awk 'BEGIN {ORS=""} //' sample
Heigh-ho! sing, heigh-ho! unto the green holly:Most friendship\
is feigning, most loving mere folly:Then, heigh-ho, the holly!$

删除了所有的换行,包括最后一个。返回的 Shell 提示符与输出数据出现在同一行中。要在结尾添加一个换行,可以将其放在 END 规则中:

$  awk 'BEGIN {ORS=""} // { print } END {print "\n"}' sample
Heigh-ho! sing, heigh-ho! unto the green holly:Most friendship\
is feigning, most loving mere folly:Then, heigh-ho, the holly!
$

更多 GAWK 变量

NF 变量包含当前记录中字段的个数。使用 NF 可以引用其数值,而使用 $NF 则表示引用实际字段本身的内容。所以,如果记录有 100 个字段,print NF 将输出整数 100,而 print $100 则与 print $NF 输出相同的结果,都是该记录中最后一个字段的内容。

NR 变量包含当前的记录个数。当读取到第 1 个记录时,其值为 1,当读取到第 2 个记录时,其值增为 2,依此类推。在 END 模式中使用它,以便输出输入中的行数:

$ awk 'END { print "Input contains " NR " lines." }' sample
Input contains 3 lines.
$

注意:如果上面的 print 语句位于 BEGIN 模式中,那么该程序将报告其输入包含 0 行内容,因为在执行时 NR 的值为 0,因为此时尚未读入任何输入记录。

使用 $NR 打印相对于当前记录个数的字段:

$ awk '{ print NR, $NR }' sample
1 Heigh-ho!
2 friendship
3 the
$

再来研究一下图 4,可以看到第 1 个记录中的字段 1 的值、第 2 个记录中的字段 2 的值,以及最后一个记录中字段 3 的值。将其与您的程序输出进行比较。

尝试列出每个记录中字段的个数,以及最后一个字段的值:

$ awk ' { print "Record " NR " has " NF " fields and ends with " $NF}' sample
Record 1 has 7 fields and ends with holly:
Record 2 has 8 fields and ends with folly:
Record 3 has 4 fields and ends with holly!

通常可以使用大量特殊的 GAWK 变量。表 2 列出了这些变量,并对其含义进行了描述。

表 2. 常见的 GAWK 变量
变量描述
NF 该变量包含每个记录的字段个数。
NR 该变量包含当前的记录个数。
FS 该变量是字段分隔符。
RS 该变量是记录分隔符。
OFS 该变量是输出字段分隔符。
ORS 该变量是输出记录分隔符。
FILENAME 该变量包含所读取的输入文件的名称。
IGNORECASE IGNORECASE 设置为非空值,GAWK 将忽略模式匹配中的大小写。

GAWK 模式匹配

在 GAWK 中,其模式匹配机制类似于 egrep 命令的模式匹配机制。要仅输出那些匹配模式的记录,可以在规则中指定该模式,使用斜杠字符括起来。

在输入记录中匹配模式

要匹配单个模式,可以在规则中进行指定:

$ awk '/green/ { print }' sample
Heigh-ho! sing, heigh-ho! unto the green holly:
$

并不仅限于字符串,该模式可以为任何扩展的正则表达式。尝试在示例输入中匹配这样的记录,包含两个感叹号,并且其中可以有任意数量的文本:

$ awk '/!.*!/' sample
Heigh-ho! sing, heigh-ho! unto the green holly:
$

grep 不同的是,您还可以在搜索中指定 ASCII 字符的十六进制和十进制值。要指定十六进制值,可以使用格式 \xNN,其中 NN 是实际字符的十六进制值。要指定十进制值,可以使用格式 \xxx,其中 xxx 是字符的十进制值。

该功能非常适合于匹配扩展的或非打印字符,如 BELL 字符(Ctrl-G,您可以与 '/\007/' 进行匹配)作为模式。然而,AWK 不能对二进制文件进行操作。

在字段中匹配模式

要在特定的字段中(相对于在整个记录中)匹配模式,可以指定该字段并使用 ~ 操作符,这表示“包含”,然后指定该模式:

$field ~ /pattern/

!~ 操作符以相反的方式进行操作,您可以使用它表示要匹配那些 包含给定模式的字段:

$field !~ /pattern/

尝试仅打印示例数据中第 3 个字段包含 s 字符的那些记录:

$ awk '$3 ~ /s/' sample
Most friendship is feigning, most loving mere folly:
$

要打印那些登录 Shell 不是 bash 的所有用户的全名,可以使用下面的命令:

$ awk 'BEGIN {FS=":"} $7 !~ /bash/ {print $5}' /etc/passwd

使用布尔操作符

您可以使用布尔操作符连接不同的模式,如表 3 所示,您可以在一个规则中使用多个布尔操作符。

表 3. GAWK 布尔操作符
操作符描述
&& 逻辑“与”操作符
|| 逻辑“或”操作符
! “非”操作符

尝试仅输出示例数据中匹配 regexpintheto 的那些记录的第 4 个字段:

$ awk '/in/ && /the/ && /to/ {print $4}' sample
unto
$

现在,打印示例数据中不包含 holly确实 包含 most 的那些记录,同时将输出记录分隔符更改为连字符:

$ awk 'BEGIN { OFS="-" } ! /holly/ || /most/ { print $1, $2 }' sample
Most-friendship
$

使用范围模式

在两个模式之间使用逗号,可以指定一个范围,这表示匹配位于这两种模式之间和模式本身的所有文本。与其他的搜索不同,范围模式在匹配文本时可以跨越不同的记录。它输出包含匹配项部分内容的完整的记录。例如,搜索从 Heighfolly 的范围,将输出前两个记录的文本:

$ awk '/Heigh/,/folly/' sample
Heigh-ho! sing, heigh-ho! unto the green holly:
Most friendship is feigning, most loving mere folly:
$

输出匹配的整段内容

如果您使用换行符作为字段分隔符、使用空字符串作为记录分隔符,那么 AWK 会将整段内容作为一个记录。这样使其成为了“段落 grep”,它将输出匹配搜索的整段内容。对于包含大量文本的文件,该功能可能非常有价值。

重定义分隔符,然后在示例文件中搜索 green。如果不进行重新定义,该搜索仅输出第 1 个记录(即第 1 行)。但是,因为整个示例文件中只有一个段落,所以该匹配将输出整个文件本身:

$ awk 'BEGIN { FS="\n"; RS="" } /green/' sample
Heigh-ho! sing, heigh-ho! unto the green holly:
Most friendship is feigning, most loving mere folly:
Then, heigh-ho, the holly!
$

总结

在本教程中,您已经开始使用 GAWK,它是 GNU Project 的 AWK 编程语言的开放源代码实现。您了解了 AWK 编程语言的一些基本知识,包括如何运行和组织程序、以及一些基本的操作,如字段和记录操作以及模式匹配。还有更多需要学习的内容,AWK 是 UNIX 功能强大的工具 中的一种,但即使是第一次接触,您也可以感觉到 AWK 语言作为一种文本操作工具所具有的强大功能。

posted on 2017-07-18 09:02  时迅  阅读(683)  评论(0编辑  收藏  举报