POSIX awk 对变量/printf 中的空字节的立场是什么?

POSIX awk 对变量/printf 中的空字节的立场是什么?

printf根据 POSIX使用 awk 函数打印空字节是否合法?这POSIX 标准awk似乎没有明确提及这两种方式。现实世界的实现在行为方式上有所不同:

+$ gawk 'BEGIN { x = sprintf("\000"); print(length(x)); }'
1
+$ busybox awk 'BEGIN { x = sprintf("\000"); print(length(x)); }'
0
+$

+$ gawk 'BEGIN { printf("\000"); }' | xxd
00000000: 00                                       .
+$ busybox awk 'BEGIN { printf("\000"); }' | xxd
+$

标准中是否有指定?如果是,变量 ( x = sprintf("\000")) 和 printf ( )所需的行为是否printf("\000")相同?

答案1

至少有 4 条相关文本POSIX.2018 规范awk

在下面所有引用的文本中,强调(粗体文本)是我的:

来自以下任何来源的 awk 程序的输入文件应为文本文件

这意味着如果输入包含 NUL 字符(根据 POSIX 文本定义,这将使其成为非文本),则行为是未指定的。

\ddd :一个 <反斜杠> 字符,后跟一个、两个或三个八进制数字字符的最长序列 (01234567)。 如果所有数字均为 0(即 NUL 字符的表示形式),则行为未定义

因此\000会导致未定义的行为。

关于正则表达式匹配:

然而,在所有 awk ERE 匹配中,在模式、输入记录或文本字符串中使用一个或多个 NUL 字符会产生未定义的结果

关于printf/ sprintf

7. 对于c 转换说明符:如果参数有数值,则应输出编码为该值的字符。如果该值为零或者不是字符集中任何字符的编码,行为未定义

因此,这是获取 NUL 字符的另一种方法,该方法会导致未定义的行为。

所以,总而言之awk,POSIX 告诉我们不能移植使用 NUL 字符,无论是用于输入、输出还是存储在变量中。

gawk(至少从 1989 年的 2.10 开始,这是我能找到的最早版本NUL 支持已记录) 和@托马斯迪基的mawk(自从版本20140914)是可以处理 NUL 的两个实现。

答案2

C 字符串一般不能包含 nul 字节,awk基本上是某种 C 解释器。需要在 POSIX 标准中明确提及能够打印 nul 字节的 POSIX 实用程序。printfawk事实并非如此。

POSIX 中明确列出了以下情况:

echo 'x\0000y'
printf 'x\000y\n'
printf '%b\n' 'x\0000y'

所有三个命令都会在具有 POSIX UNIX 品牌的经过认证的操作系统上打印四个字符。

您的awk示例使用了未指定的行为。

相关内容