从awk和nawk得到不同的结果

3

我刚刚在一份约有2.5亿条记录的文件上运行了这两个命令。

awk '{if(substr($0,472,1)=="9") print $0}' < file1.txt >> file2.txt

并且

nawk '{if(substr($0,472,1)=="9") print $0}' < file1.txt >> file2.txt

记录长度为482。第一个命令给出了file2.txt文件中正确的记录数量,即6000万条,但是nawk命令只给出了420万条。
我感到困惑,想知道是否有人遇到过这样的问题。这个简单的命令在内部被如何处理?使用nawk时是否有一个缓冲区仅能容纳一定数量的字节?
如果有人能对此进行解释,我将不胜感激。
我的操作系统详细信息如下:
SunOS <hostname> 5.10 Generic_147148-26 i86pc i386 i86pc

如果命令没有出现错误,那么很可能是nawk中的缓冲区被设置为了一个限制。 - konsolebox
@shellter,我尝试使用nawk '{if(substr($0,472,1)=="9") print $0}' < file1.txt > file3.txt,结果是一样的。另外4.2m+1似乎是正确的,被awk捕获但不是nawk。 - Ankit
@Ankit 你可能可以在 nawk 的源代码中看到这一点。 - konsolebox
1
@konsolebox: 什么缓冲区限制?除了行大小,nawk(应该)一次处理一行,对吧?我曾经用nawk处理过大约1000万行的文件,那时候期望它能够处理任意数量的行。@Ankit:请向我们展示which awkwhich nawk的结果。祝大家好运! - shellter
@Ankit,在你的问题中,你说:“第一条命令给出了file2.txt中正确的记录数,即6000万,但nawk命令只给出了420万。”但是在你上面的评论中,你又说相反的话:“也许4.2m+1才是正确的,它被awk捕获了,但没有被nawk捕获。”请明确说明你认为哪个输出是正确的,哪个工具产生了该输出。 - Ed Morton
显示剩余2条评论
2个回答

7

问题可能在于Nawk的缓冲限制上。你的输入文件中的某一条记录(行)可能已经超过了它的限制。

这个关键的代码可以在awk.h中找到:

#define RECSIZE (8 * 1024)  /* sets limit on records, fields, etc., etc. */

1
每天学点新东西!仍然希望能看到 @Ankit 访问的是哪个 awk,如果是 /usr/bin/awk,那我会非常惊讶,而如果是 /usr/xpg4/bin/awk,那就有趣了。此外,我不会认为在 netbsd.org 上找到的东西与在 "SunOS <hostname> 5.10" 上找到的 nawk 是一样的,但我可能也错了 ;-!) 祝大家好运。 - shellter
3
@Ankit 您写道“记录长度为482”。一个长度为(8*1024)的记录似乎不可能是有效的记录。祝好运。 - shellter
我同意 @shelter 的观点。如果每行的长度为482个字符,则不会超过任何一个记录的缓冲区大小。而且,如果每个记录的大小都相同,那么它们全部都会超过缓冲区大小,而不仅仅是其中一些。这里肯定还有其他问题。 - Ed Morton
我承认我实际上并没有太在意(也没注意到)记录长度(指定的那个)。我一直在想行数(6000万/420万),在这么多行中,有些行可能比常见的更长。不过看到注释后,我同意还有另一种可能性。 - konsolebox
@konsolebox 那么解决方案是编辑这个 .h 文件吗? - lolololol ol
@lololololol 嗯,黑客攻击 awk 实用程序是一种“解决方案”,但除非我再次研究源代码,否则我无法回答你的问题。然而,如果您决定对其进行黑客攻击,我建议您首先确认问题是否仍存在于最新版本的 nawk 中,并且“RECSIZE”限制实际上是导致问题的原因。 - konsolebox

2
您的命令可以简化为以下内容:
awk 'substr($0,472,1)==9'

在 Solaris 上(您当前使用的操作系统),默认情况下运行的是旧版且有缺陷的 awk(/usr/bin/awk),所以我猜测 nawk 是产生正确结果的那个。

请使用相同的脚本和参数运行 /usr/xpg4/bin/awk,并查看其输出结果与其他结果哪一个相符。

此外,请运行 dos2unix 命令检查您的输入文件是否是在 Windows 上创建的,如果大小发生变化,则在修改后的文件上重新运行 awk 命令。如果该文件是在 Windows 上创建的,则其中可能包含一些控制字符,这可能会导致混乱。


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接