GNU Awk 4.1:老鸟学新招,第二部分
在之前的一篇文章(“GNU Awk 4.0:老鸟学新招”,发表于 2011 年 9 月刊的Linux Journal)中,我简要介绍了 awk
和 gawk
的历史,并对 gawk
4.0 中的许多新功能进行了高层次的概述。我建议您先阅读那篇文章,当然,如果您愿意,也可以不读那篇文章直接阅读这篇。
gawk
4.0 本身于 2011 年 6 月发布。自那时以来,gawk
开发团队并没有止步不前!gawk
4.1 于 2013 年 5 月发布,包含许多新功能,这就是我在此处要介绍的内容。
与 gawk
4.0 不同,这次在语言层面的更改要少得多(尽管仍然有一些)。这次的更改更多地关注内部机制以及与外部世界交互的能力。那么,让我们开始吧。
多年来,当您构建 gawk
时,您会得到两个可执行文件:常规解释器 gawk
和其性能分析孪生兄弟 pgawk
,后者运行 awk
程序(速度较慢)并生成语句计数执行配置文件,显示每行代码执行了多少次。
在 gawk
4.0 中,您又获得了一个额外的可执行文件 dgawk
,即 gawk
调试器。尽管这三个版本共享了大部分相同的代码,但实际执行 awk
程序的内核部分在每个版本中都是以不同的方式编译的。
对于 gawk
4.1,所有三个可执行文件都已合并到一个名为 gawk
的程序中。尽管合并后的可执行文件更大,但它仍然比拥有三个独立的可执行文件要小,此外,文档也更简单易懂(且易于维护!)。
为了适应此更改,选项必须稍作更改。您现在可以使用 -D
运行调试器,使用 -p
进行性能分析,使用 -o
进行美化打印而不进行性能分析。
对于 awk
程序员来说,一个重要的新功能是使用 GNU MPFR 和 GMP 库进行任意精度浮点算术。
这是一个可选功能:如果您在配置和构建 gawk
时安装了 MPFR 和 GMP 库,则 gawk
将自动能够使用它们。
请注意,我说的是“能够使用它们”。您仍然必须选择使用 -M
选项(或 --bignum
,如果您喜欢长选项),或者将特殊变量 PREC
设置为所需的浮点精度。
精度是浮点尾数中保留的位数。默认值为 53,这与硬件双精度浮点数使用的精度相同。摘自 gawk
手册
$ gawk -M -v PREC=100 'BEGIN { x = 1.0e-400; print x + 0}
> PREC = "double"; print x + 0 }'
1e-400
0
您会看到常规硬件无法处理 -400 的指数,而 MPFR 可以。
另一个新的变量 ROUNDMODE
设置了计算和打印任意精度值的舍入模式。
在过去的几年中,由于一些我不太明白的原因,我收到了人们的错误报告,他们期望 gawk
的算术运算与用纸和笔进行的“真实”算术运算完全相同。换句话说,他们想要计算机科学中所谓的十进制算术。我不确定他们为什么期望这样,但正如我们都应该知道的那样,计算机并非完全以这种方式工作。
MPFR 不会为您提供十进制算术。但是,如果您了解自己在做什么以及如何使用它,您可以获得可能足以满足您目的的结果。
该手册有一整章描述了与浮点算术相关的问题,增加精度意味着什么,以及如何使用 MPFR 支持的各种舍入模式。
新数组提供间接变量访问有三个新数组
-
SYMTAB
:提供对awk
级别变量的访问。 -
FUNCTAB
:列出所有用户定义函数和扩展函数的名称。 -
PROCINFO["identifiers"]
:列出所有已知的标识符以及gawk
在解析程序后了解的其类型。
其中,SYMTAB
最有趣,因为它提供了对任何变量的间接访问。例如
$ gawk 'BEGIN { a = 5 ; print "a =", a
> SYMTAB["a"] += 37
> print "a is now", a }'
a = 5
a is now 42
使用 isarray()
内置函数,您可以“遍历”整个符号表并打印出所有变量和数组值(如果您选择这样做)。
gawk
4.1 中最令人兴奋的改变是其与外部世界交互的能力。多年来,gawk
具有一种“扩展”或“插件”机制,允许程序员用 C 语言编写新的“内置”函数,并在运行时将其加载到正在运行的 gawk
解释器中。
这种机制需要了解一些 gawk
的内部机制,并利用 gawk
的内部数据结构和函数。尽管文档记录很少,并且它可以工作,但它有几个缺点。最显着的缺点是跨版本没有向后兼容性。
尽管如此,一组开发人员还是 fork 了 gawk
以创建 xgawk
(XML gawk
),并为核心可执行文件开发了许多动态扩展和新功能。
多年来,我一直想为编写扩展提供定义的 C API,该 API 不依赖于 gawk
内部机制,并且可能在不同版本之间提供二进制兼容性。
对于 gawk
4.1,我们与 xgawk
开发人员一起,最终实现了这一点。
为什么需要扩展?
考虑一下:awk
程序甚至无法使用 chdir
系统调用来更改其工作目录!因此,awk
是一种封闭的语言——一种仅为您提供实现者选择提供的功能,仅此而已。这没什么乐趣。(好吧,awk
很有趣,但它仍然有限。)
相比之下,现代脚本语言都是开放且可扩展的;Perl、Tcl、Python 和 Ruby 都拥有数千个可在运行时加载的可用模块。gawk
也应该能够做到这一点,这已经过时了。
您可以从扩展中做什么
最好将扩展函数视为用另一种语言编写的用户定义函数。它们不能做用户定义函数可以做的所有事情(例如调用 awk
函数、操作字段、使用 getline
读取记录等等),但它们可以做的事情足以使 gawk
更加开放,并使其与底层操作系统和其他 C(或 C++)库接口。特别是,您可以
-
按值传递标量,按引用传递数组。
-
创建和修改新的全局变量和数组。
-
访问内置变量(只读,尽管您可以更新
PROCINFO
)。 -
注册一个在
gawk
退出时调用的函数。 -
打印警告和/或致命错误消息。
-
更新内置变量
ERRNO
以在出现问题时使用。 -
Hook 进入 I/O 重定向机制,提供您自己的“特殊”文件名和/或双向通信器。
-
当然,注册可以从
gawk
调用的新函数。
API 提供了许多数据类型,以便更轻松地与 gawk
通信。例如,gawk
字符串可以包含嵌入的 NUL 字符(所有位均为零),因此字符串具有指针和长度。gawk
在内部维护引用计数的字符串,因此有方法告诉 gawk
重用它已经知道的值。
此外,API 允许您将 awk
的关联数组“展平”为结构数组,以便在 C 代码中轻松迭代,而无需在每次想要移动到数组中的下一个元素时都调用 gawk
。
API 的完整描述超出了本文的范围;但是,该手册包含一整章,其中包含示例,描述了 API 并展示了如何使用它。
操作系统独立性
扩展机制旨在在多个操作系统上工作。在撰写本文时,它可以在任何支持 POSIX dlopen()
API 的 *nix 系统上工作。这包括 Mac OS X。基本机制也适用于使用 MinGW 的 Microsoft Windows。但是,由于尚未准备就绪,因此 4.1 版本中未包含构建示例扩展的支持。此支持将包含在第一个补丁版本中,无论何时发布,尽管并非所有示例扩展都可以在 Windows 上工作。
示例扩展
gawk
发行版提供了许多小型示例扩展。它们的主要目的是作为如何使用 API 的示例,但尽管如此,它们也应该可以用于实际工作。完整列表在手册中有所记录。一些更有趣的包括
-
“filefuncs”扩展,提供
chdir()
和stat()
函数,以及 fts(3) 例程套件的接口,用于遍历文件层次结构。 -
“fnmatch”扩展,提供 fnmatch(3) 套件的
awk
版本。 -
“readdir”扩展,它为
gawk
命令行上命名的目录或使用getline
读取的目录返回内容记录。(通常,尝试读取目录是非致命错误。对于其他awks
,这是致命的。) -
“inplace”扩展,它模拟 GNU
sed -i
功能,用于就地编辑命令行数据文件。
其他更专业的扩展说明了 API 的某些部分的使用,这些部分未在刚刚列出的扩展中涵盖。
gawkextlib 项目
现在 gawk
支持主要的 xgawk
功能,xgawk
开发人员已将其项目围绕其特定扩展进行了重新定位。它不再包括 fork 的 gawk
代码库。为了强调这种方向的改变,他们将其项目重命名为“gawkextlib”。
他们(和我的)希望该项目可以作为 awk
社区随着时间的推移可能编写的新 gawk
扩展的中央信息交换中心。
gawkextlib 项目目前有四个扩展
-
XML 扩展,它添加了几个新变量和一个输入解析器,使
gawk
能够以自然的方式解析 XML 文件。此扩展构建在 Expat XML 解析器之上。这是一个强大的扩展;您不必尝试手动使用正则表达式解析 XML 文件,Expat 解析器会为您完成,包括所有在纯awk
代码中很难完成的令人讨厌的验证工作。 -
PostgreSQL 扩展,它提供了与 PostgreSQL 数据库通信的函数。
-
GD 图形库扩展,用于 GD 图形库(请参阅资源)。
-
MPFR 库扩展。此扩展使您可以访问许多无法从
gawk
的内置 MPFR 支持访问的 MPFR 函数。
我觉得 gawk
作为一种语言已经基本成熟,并且不希望添加太多新功能。也就是说,仍然有一些项目有待探索
-
额外的数字功能,例如可能与十进制算术库集成。
-
一种将
gawk
数组映射到外部存储的方法,例如 DBM 数组或 SQL 数据库。 -
扩展函数和变量以及可能的常规
gawk
级别变量和函数的“命名空间”功能。这将是一项重大的设计活动。
当然,描述上述项目并不构成承诺要执行其中任何一项。
结论新的 API 和扩展工具为 gawk
和 awk
程序员开辟了新的视野。我对此感到非常兴奋,并且我希望看到 gawk
被用于许多以前根本不适用的新事物。
感谢 Scott Deifik、Brian W. Kernighan 博士、Nelson Beebe 博士和 Eli Zaretskii 对本文初稿的评论。
整个 gawk
开发团队都值得称赞他们为这个版本所做的工作。这在很大程度上是一项团队努力。
“GNU Awk 4.0:老鸟学新招”,LJ,2011 年 9 月:http://www.linuxjournaldigital.com/linuxjournal/201109#pg94
gawk
发行版:http://ftp.gnu.org/gnu/gawk/gawk-4.1.0.tar.gz
在线文档:https://gnu.ac.cn/software/gawk/manual
使用 gawk
的任意精度算术:https://gnu.ac.cn/software/gawk/manual/html_node/Arbitrary-Precision-Arithmetic.html#Arbitrary-Precision-Arithmetic
动态扩展:https://gnu.ac.cn/software/gawk/manual/html_node/Dynamic-Extensions.html#Dynamic-Extensions
gawkextlib 主页:http://gawkextlib.sourceforge.net
gawkextlib 下载:http://sourceforge.net/projects/gawkextlib
GD 图形库:http://www.boutell.com/gd/manual2.0.33.html
Expat XML 解析器:http://expat.sourceforge.net