我正在编写一个需要在 Apple MacO 和 Ubuntu 之间移植的脚本。前者的“awk”是(我相信)由nawk提供,而后者是gawk提供的。实现之间存在显着差异。
具体来说,我正在 Ubuntu 22.04LTS 上进行开发,不幸的是......
# apt install nawk
Reading package lists... Done
Building dependency tree... Done
Reading state information... Done
E: Unable to locate package nawk
(在 Debian Bullseye 上也是如此)
我还尝试下载 nawk 源代码并进行编译,但是 yacc 在我的发行版上不可用,并且 Bison 的兼容性不足以运行 makefile。
有没有办法让gawk表现像诺克?
如果做不到这一点,是否有一个 Linux 发行版可以从存储库中获得 nawk?
答案1
nawk
是的,其存储库中至少有一个发行版。我确信有很多,但我是通过我的 Arch 系统写这篇文章的,我可以确认 Arch 具有nawk
:
$ pacman -Ss nawk
community/nawk 20220912-1 [installed]
The one, true implementation of AWK
也就是说,这里一个有用的技巧是使用 busybox awk
。忙碌盒是一个很棒的工具,非常有用并且常见于嵌入式系统,它提供了各种标准工具的精简版本:
BusyBox 将许多常见 UNIX 实用程序的微型版本组合到一个小型可执行文件中。它提供了您通常在 GNU fileutils、shellutils 等中找到的大多数实用程序的替代品。BusyBox 中的实用程序通常比其全功能的 GNU 同类程序具有更少的选项;然而,其中包含的选项提供了预期的功能,并且行为与 GNU 对应选项非常相似。 BusyBox 为任何小型或嵌入式系统提供了相当完整的环境。
它提供的工具之一是awk
,因此如果您安装busybox
在 Ubuntu ( sudo apt install busybox
) 中,则可以运行busybox awk
以获得最小的awk
.这是不是 nawk
,但它是一个简单、精简的版本awk
,它应该提供比gawk
.如果您的脚本适用于 busybox awk
,那么它很可能也适用于gawk
和nawk
。这不是一个完美的解决方案,我确实找到了一条评论该网站上的另一个答案声称“实际上,BusyBox 的awk
行为与gawk
v3 非常接近;我认为它的功能比nawk
,但这只是一个开始。
最后,也许是最相关的,gawk
实际上有一个--posix
选项:
-P
--posix
在严格的 POSIX 模式下运行。这将禁用所有 gawk 扩展(就像 --traditional 一样)并禁用 POSIX 不允许的所有扩展。看常用扩展总结有关 gawk 中被此选项禁用的扩展的摘要。此外,还适用以下附加限制:
'?' 之后不允许换行或“:”(参见条件表达式)。在命令行上指定“-Ft”不会将 FS 的值设置为单个制表符(请参阅指定字段的分隔方式)。语言环境的小数点字符用于解析输入数据(请参阅你所在的位置会有所不同)。
如果您在命令行上同时提供 --traditional 和 --posix,则 --posix 优先。如果提供了两个选项,gawk 会发出警告。
因此,最好的选择是gawk --posix
在测试时使用,以确保只使用便携式功能。
或者,也可能不是。埃德·莫顿我们的一位常驻 awk 专家在一条现已删除的评论中这样说道:
gawk --posix
并不能确保您只使用便携式功能。例如,使用该选项集split("foo",arr,"")
将填充arr[]
字符串中的每个字符"foo"
,但其他 awks 可以填充arr[]
整个字符串的单个条目"foo"
或执行其他任何操作并符合 POSIX,因为使用空字符串作为分隔符的字段拆分是未定义的行为。所做--posix
的就是关闭 gawk 扩展,但您仍然需要手动注意编写依赖于 POSIX 未定义的任何行为的 gawk 实现的代码。 ——埃德·莫顿
Ed 对 awk 的了解比我多得多,所以我相信他的话。
答案2
经过更多搜索后,我找到了更新版本的 nawk (或者至少我相信这是nawk),路标来自https://www.cs.princeton.edu/~bwk/btl.mirror/index.html在https://github.com/onetrueawk/awk
不过我仍然有兴趣看看是否有人有更好的建议。
答案3
这类问题的答案是你需要一个跨平台的项目。
您应该能够在必须运行的平台上检查您的项目,运行所需的任何准备工作,然后执行测试用例套件。
每当您发布脚本的新版本时,您都必须执行该测试计划:在所有受支持的平台上更新到发布基线,运行测试用例,并执行您拥有的任何其他测试计划,以获得事情正常运行的信心每个支持的平台。
只要小心一点,您应该能够编写在 GNU Awk、nawk 等中产生相同结果的 Awk 代码。
nawk 源代码并进行编译,但是 yacc 在我的发行版上不可用,并且 Bison 不够兼容
我发现“One True Awk”项目做了一些非常愚蠢的事情。定义.makefile
YACC = bison -d
这意味着awkgram.y
语法文件现在受到用户安装的任何 Bison 版本的默认行为的影响。使问题更加复杂的是,该项目没有提供维护者实际构建和测试的生成的解析器源。因此,下游用户为程序的相当重要的部分运行不同的 C 代码。
如果您在安装 Bison 时遇到困难,请尝试将其更改为bison --yacc -d
. 没有or参数bison
就不是真正的 Yacc 。-y
--yacc
如果失败,请在其他平台上生成解析器,并使用这些生成的文件。
即使您让 nawk 在平台 A 上运行,也不意味着您可以假设您的代码无需测试即可在平台 B 上运行。
无论如何,它看起来像一个真正的 awk源代码不包含 Yacc 生成的解析器,这是一个错误。您可以做的就是在适用的平台上运行 Yacc,然后将结果y.tab.c
和y.tab.h
文件添加到本地树中。确保您触摸了时间戳,以便这些文件比这些文件更新,awkgram.y
这样makefile
就不会尝试重建它们;或者调整makefile
.
Yacc 程序生成可移植的 C 输出,以便下游用户无需安装 Yacc 即可构建该程序。使用 Yacc 语法的项目应该始终发布生成的代码,以便下游的每个人都编译相同的 C。当人们拥有相同的 C 源代码,但为不同的机器和环境构建它们时,这已经足够危险了。
我很惊讶 Bison 无法处理awkgram.y
Brian Kernighan 的 awk 中的文件。你必须使用bison --yacc
或bison -y
。在 Bison 提供 Yacc 实现的系统上,通常有一个名为 的脚本yacc
将其参数传递给bison -y
或bison --yacc
。我刚刚检查了https://github.com/onetrueawk/awk.git
一个 Ubuntu 18 实例,其中默认安装了 Bison 3.0.4,以及/usr/local/bin
.两人都awkgram.y
无误地接受。