使用getline

时间:2016-01-21 17:40:32

标签: bash awk gawk

这是交易:我需要读取特定字节数,稍后将对其进行处理。我遇到了一个奇怪的现象,我无法绕过它。也许别人? :)

注意:以下代码示例是精简版本,只是为了显示效果!

这样做(至少使用gawk)是将RS设置为全部正则表达式,然后使用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/中。然后我需要做一些最后的处理步骤。上面的示例只是最简单的脚本,以显示问题。

2 个答案:

答案 0 :(得分:1)

似乎这是报告错误here的一种表现形式,如果我理解正确的话,它会在接近输入结束时过早地终止getline,而不是输入的结束。

错误修复似乎已在2014年May 9May 10上提交,因此如果您可以升级到版本4.1,则应该解决问题。

如果你需要做的只是读取指定的字节数,我建议awk不是理想的工具,不管错误。相反,您可以考虑以下两个标准实用程序之一,它们将能够更有效地完成工作:

head -c $count

dd bs=$count count=1

使用dd,如果stdin / stdout不合适,您可以显式设置输入文件(if=PATH)和输出文件(of=PATH)。使用head,您可以将输入文件指定为位置参数,但输出始终转到stdout。

有关详细信息,请参阅man headman dd

答案 1 :(得分:0)

幸运的是,使用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