使用空字符串拆分单个字符

使用空字符串拆分单个字符

我在 Gawk 手册中读到:

GNU 扩展

[...]

使用空字符串作为 FS 的值以及 split() 的第三个参数来分割单个字符的能力。

然而事实似乎并非如此。这按预期工作:

$ gawk 'BEGIN {print split("quebec", z, "")}'
6

我可以禁用其他扩展:

$ export POSIXLY_CORRECT
$ gawk 'BEGIN {typeof(1)}'
gawk: cmd. line:1: fatal: function `typeof' not defined

但我无法禁用拆分行为:

$ export POSIXLY_CORRECT
$ gawk 'BEGIN {print split("quebec", z, "")}'
6

$ gawk --posix 'BEGIN {print split("quebec", z, "")}'
6

我还看了 Mawk 手册:

如果 FS = "",则 mawk 将记录分解为单个字符,类似地,split(s,A,"") 将 s 的单个字符放入 A 中。

[...]

Posix 明确保留 FS = "" 的行为未定义,并提到将记录拆分为字符作为可能的解释,但目前这种用法不可跨实现移植。

那么,通过什么实现不能使用FSand 获得单个字符呢split

答案1

这不是 POSIX,因为您不能在 POSIX 脚本中使用它,因为 POSIX 保留了该行为未指定。这意味着,虽然应用程序(脚本)如果想要可移植就不能使用它,但实现(实现awk)可以做任何它想做的事情,只要你这样做并且仍然是 POSIX。 POSIX 不需要awk分割成字符或字节,或者报告错误,或者重新启动计算机,它不会指定。

因此,gawk当处于环境中时,没有理由改变其在这方面的行为,在$POSIXLY_CORRECT这种情况下,没有任何行为比其他行为更 POSIX 正确。

正如您所发现的,该扩展存在于 gawk(自 3.0,1996 年 1 月起)和 mawk(自 1.2 版,1996 年 1 月起)中。它也在 busybox 中awk(从一开始(2002 年)),并且自 1996 年 5 月以来也在 Brian Kernighan 维护的(kawk)中(该FIXES文件引用gawk, ETC。作为灵感)。看起来它是在几个月内添加到所有 3 个中的,这表明它们的维护者可能对此进行了讨论。我现在不太确定是谁先想到这个主意的。

对于 Brian Kernighan 的awk或基于它的(如 FreeBSD 或 OpenBSD 上的),请注意,虽然FS传递给的空或空的第三个参数split()会导致字符串被拆分为各个字符(嗯,字节,见下文),awk -F ''返回一个错误(awk -v FS=不过没关系)。

在 Solaris 上,对于nawkand /usr/xpg4/bin/awk(以及/bin/awk70 年代的旧版本),空FS似乎完全禁用了拆分。nawk -F ''返回错误。我希望它在其他基于 AT&T 代码(如 AIX 或 HP/UX)的商业 Unices 上也是一样的,尽管我无法在那里测试它。

另请注意mawk,bwk awk(对于某些人来说这是不同的)基于上)和 busybox awk 不支持多字节字符。例如,在 UTF-8 中:

echo Stéphane | awk -v FS= '{print $4}'

会打印我名字中第三个字符的后半部分。因此,对于这些,更正确的说法是空 FS 分割成单独的字节,而不是字符。


1 我现在意识到,使用 POSIXLY_CORRECT 或--posixgawk禁用了一些不与 POSIX 冲突的扩展(尽管typeof确实gawk不兼容),所以你可以说这是一个遗漏。现在这已经不是第一个了。例如,nextfile即使它确实与 POSIX 冲突(awk '{nextfile = 1}'意味着将 1 分配给变量,但即使在 POSIXLY_CORRECT 下nextfile也会报告错误),它也不会禁用。gawk

相关内容