我在 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 = "" 的行为未定义,并提到将记录拆分为字符作为可能的解释,但目前这种用法不可跨实现移植。
那么,通过什么实现不能使用FS
and 获得单个字符呢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 维护的(k
在awk
)中(该FIXES
文件引用gawk
, ETC。作为灵感)。看起来它是在几个月内添加到所有 3 个中的,这表明它们的维护者可能对此进行了讨论。我现在不太确定是谁先想到这个主意的。
对于 Brian Kernighan 的awk
或基于它的(如 FreeBSD 或 OpenBSD 上的),请注意,虽然FS
传递给的空或空的第三个参数split()
会导致字符串被拆分为各个字符(嗯,字节,见下文),awk -F ''
返回一个错误(awk -v FS=
不过没关系)。
在 Solaris 上,对于nawk
and /usr/xpg4/bin/awk
(以及/bin/awk
70 年代的旧版本),空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 或--posix
,gawk
禁用了一些不与 POSIX 冲突的扩展(尽管typeof
确实gawk
不兼容),所以你可以说这是一个遗漏。现在这已经不是第一个了。例如,nextfile
即使它确实与 POSIX 冲突(awk '{nextfile = 1}'
意味着将 1 分配给变量,但即使在 POSIXLY_CORRECT 下nextfile
也会报告错误),它也不会禁用。gawk