GAWK 过早的 EOF 与 getline
GAWK premature EOF with getline
事情是这样的:我需要读取特定数量的字节,这将在稍后处理。不过,我遇到了一个奇怪的现象,我无法理解它。也许是别人? :)
注意:以下代码示例是精简版,只是为了展示效果!
一种方法,至少对于 gawk
,是将 RS
设置为包罗万象的 regex,然后使用 RT
看看,匹配到了什么:
RS="[\x00-\xFF]"
然后,非常简单地使用以下 awk-script:
BEGIN {
ORS=""
OFS=""
RS="[\x00-\xFF]"
}
{
print RT
}
这工作正常:
$ echo "abcdef" | awk -f bug.awk
abcdef
但是,我需要访问几个文件,所以我不得不使用 getline
:
BEGIN {
ORS=""
OFS=""
RS="[\x00-\xFF]"
while (getline)
{
print RT
}
}
这貌似相当于上面的,但是当运行它的时候,有一个令人讨厌的惊喜:
$ echo "abcdef" | awk -f bug.awk
abc
这意味着,出于某种原因,getline
遇到 EOF 条件 提前 3 个字节。那么,我是不是错过了什么,我应该了解 bash/Linux 缓冲的内部结构,还是我发现了一个可怕的 bug?
仅作记录:我在 Ubuntu 14.04 LTS (Linux 3.13.0/36)
上使用 GNU Awk 4.0.1
伙计们,有什么建议吗?
更新:我正在使用 getline
,因为我之前已经读取并预处理了文件,并存储在文件 /dev/shm/
中。然后我需要做一些最后的处理步骤。上面的例子只是最低限度的脚本,用来说明问题。
幸运的是,使用 GNU Awk 4.1.3(在 Mac 上),带有 getline 的程序按预期运行:
echo "abcdef" | gawk 'BEGIN{ORS="";OFS="";RS="[\x00-\xFF]";
while (getline) {print RT}}'
abcdef
$ gawk --version
GNU Awk 4.1.3, API: 1.1
这似乎是报告的错误 here 的表现,它(如果我理解正确的话)具有在接近输入结束时过早终止 getline
的效果,而不是比输入结束时。
错误修复似乎已于 2014 年 May 9 and May 10 提交,因此如果您可以升级到 4.1 版,它应该可以解决问题。
如果您需要做的只是读取指定数量的字节,我建议 awk
不是理想的工具,无论是否存在错误。相反,您可以考虑使用以下两个标准实用程序之一,它们可以更有效地完成工作:
head -c $count
或
dd bs=$count count=1
使用 dd
如果 stdin/stdout 不合适,您可以明确设置输入文件 (if=PATH
) 和输出文件 (of=PATH
)。使用 head
您可以将输入文件指定为位置参数,但输出始终转到标准输出。
事情是这样的:我需要读取特定数量的字节,这将在稍后处理。不过,我遇到了一个奇怪的现象,我无法理解它。也许是别人? :)
注意:以下代码示例是精简版,只是为了展示效果!
一种方法,至少对于 gawk
,是将 RS
设置为包罗万象的 regex,然后使用 RT
看看,匹配到了什么:
RS="[\x00-\xFF]"
然后,非常简单地使用以下 awk-script:
BEGIN {
ORS=""
OFS=""
RS="[\x00-\xFF]"
}
{
print RT
}
这工作正常:
$ echo "abcdef" | awk -f bug.awk
abcdef
但是,我需要访问几个文件,所以我不得不使用 getline
:
BEGIN {
ORS=""
OFS=""
RS="[\x00-\xFF]"
while (getline)
{
print RT
}
}
这貌似相当于上面的,但是当运行它的时候,有一个令人讨厌的惊喜:
$ echo "abcdef" | awk -f bug.awk
abc
这意味着,出于某种原因,getline
遇到 EOF 条件 提前 3 个字节。那么,我是不是错过了什么,我应该了解 bash/Linux 缓冲的内部结构,还是我发现了一个可怕的 bug?
仅作记录:我在 Ubuntu 14.04 LTS (Linux 3.13.0/36)
上使用 GNU Awk 4.0.1伙计们,有什么建议吗?
更新:我正在使用 getline
,因为我之前已经读取并预处理了文件,并存储在文件 /dev/shm/
中。然后我需要做一些最后的处理步骤。上面的例子只是最低限度的脚本,用来说明问题。
幸运的是,使用 GNU Awk 4.1.3(在 Mac 上),带有 getline 的程序按预期运行:
echo "abcdef" | gawk 'BEGIN{ORS="";OFS="";RS="[\x00-\xFF]";
while (getline) {print RT}}'
abcdef
$ gawk --version
GNU Awk 4.1.3, API: 1.1
这似乎是报告的错误 here 的表现,它(如果我理解正确的话)具有在接近输入结束时过早终止 getline
的效果,而不是比输入结束时。
错误修复似乎已于 2014 年 May 9 and May 10 提交,因此如果您可以升级到 4.1 版,它应该可以解决问题。
如果您需要做的只是读取指定数量的字节,我建议 awk
不是理想的工具,无论是否存在错误。相反,您可以考虑使用以下两个标准实用程序之一,它们可以更有效地完成工作:
head -c $count
或
dd bs=$count count=1
使用 dd
如果 stdin/stdout 不合适,您可以明确设置输入文件 (if=PATH
) 和输出文件 (of=PATH
)。使用 head
您可以将输入文件指定为位置参数,但输出始终转到标准输出。