Bash 使用getline查看早期EOF

Bash 使用getline查看早期EOF,bash,awk,gawk,Bash,Awk,Gawk,这里的交易:我需要读取特定数量的字节,这将在以后处理。不过,我遇到了一个奇怪的现象,我无法控制它。也许是其他人?:) 注意:下面的代码示例是精简版本,只是为了显示效果 至少在gawk中,这样做的一种方法是将RS设置为catch-all正则表达式,然后使用RT查看匹配的内容: RS="[\x00-\xFF]" 然后,非常简单地使用以下awk脚本: 这很好: $ echo "abcdef" | awk -f bug.awk abcdef 但是,我需要访问几个文件,因此我不得不使用getline:

这里的交易:我需要读取特定数量的字节,这将在以后处理。不过,我遇到了一个奇怪的现象,我无法控制它。也许是其他人?:)

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

至少在
gawk
中,这样做的一种方法是将
RS
设置为catch-all正则表达式,然后使用
RT
查看匹配的内容:

RS="[\x00-\xFF]"
然后,非常简单地使用以下awk脚本:

这很好:

$ 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
提前3个字节遇到了EOF条件。那么,我是否错过了一些我应该了解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

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

bug修复似乎已于2014年和提交,因此如果您可以升级到4.1版,它应该可以修复问题


如果您需要做的只是读取指定数量的字节,那么我建议无论有什么bug,
awk
都不是理想的工具。相反,您可以考虑以下两个标准实用工具中的一个,这将能够更有效地完成工作:

head -c $count

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


有关更多详细信息,请参阅和。

我现在没有办法测试这一点,但我希望
awk
能够在不需要getline的情况下从cmd行中获取文件列表。您是否使用多个文件尝试了原始代码?加上uno,用于精心研究的问题。但是,是的,您的测试似乎应该有效,并且不清楚您丢失数据的原因。哦您的数据中是否有
\r\n
行结尾?如果是这样,
dos2unix文件
。|tr-d'\015'|…
。继续发帖,祝你好运。好吧,我正在做的是从
stdin
中读取,并将其放入
/dev/shm
中的临时文件中,然后将该文件读回,并进行一些处理。(数据应该通过
nc
)来自网络,非常感谢,我正在尽最大努力……)陛下你说“但是,我需要几个文件,以便访问…”。对于其他读者,您可能希望澄清您的
echo abcedfg | awk..
会影响您真正想要如何处理此问题。祝你好运为了好玩,可以尝试在
while
循环之后放置一个
打印“
”,以防由于某种原因导致某些延迟输出无法刷新。
我需要几个文件才能访问,所以我不得不使用getline
——这条语句完全不清楚,因为awk在读取多个文件时不需要getline,而且一旦您告诉我们您是从
stdin
而不是从任何文件读取,它就变得更不清楚了。请编辑您的问题,明确说明awk从何处获取输入,如果您认为需要使用
getline
,请明确说明原因。如果
getline
失败,这将导致无限循环。请参见。仅针对记录,根据it't should not:
[…]如果找到记录,getline命令将返回1,如果遇到文件结尾,则返回0。[…]
@Dan:您遗漏了下一句话:“如果有错误……getline返回-1”-1,就像1一样,是真的。那么,我确实遇到了一个错误。我不是问,你是怎么知道这件事的你说得对,
awk
可能不是用于此目的的合适工具。但问题是,我必须处理基于行的数据,其中偶尔会有八位字节块,所以尝试摆脱这一点很有诱惑力。但我没有。:)@丹:我不知道,但我验证了它发生在v4.0而不是v4.1上,因为我两个版本都有。然后我在错误列表中搜索getline,这使得它很容易找到。祝项目顺利。
head -c $count
dd bs=$count count=1