使用awk的内存不足

时间:2014-03-05 01:03:29

标签: csv awk memory-leaks

我使用awk处理CSV数据文件。我的数据文件中有三个字段,例如文件a.txt。我希望awk从另一个文件b.txt中读取一个字段,然后如果第一列与读取的表达式匹配b.txt,则从我的a.txt中写入该行。我发现以下内容可以做我想做的事。

awk 'BEGIN {FS=","} { while(getline l < "b.txt") PATS[l] }ok=0;{for (p in PATS) if ($1 ~ p) ok=1}; ok {print $0}' < a.txt

然而,我遇到了巨大的内存泄漏,程序退出时出现内存错误。 a.txt约为41000行。如果有人能指出我的记忆力和/或提出替代解决方案,我将不胜感激。

2 个答案:

答案 0 :(得分:5)

使用getline验证这样的两个文件不是一个好主意,很可能是您的问题的根本原因。有getline函数有很多注意事项,尽管它是一个很好的工具,但它经常被误用。

我建议使用awk内置变量NRFNR来扫描b.txt文件并将其存储在数组中。加载数组后,如果$1与数组的键匹配,则可以从a.txt检查awk -F, 'NR==FNR{PATS[$0]++;next}$1 in PATS' b.txt a.txt

类似的东西:

NR

注意我在awk命令后放置了两个文件。这样做,直到FNRFNR相同(对于第一个文件只相同,在第一个文件完成后,PATS将重置为1)我们创建一个名为next并使用整行作为关键字。 awk阻止第二个b.txt语句运行。完成a.txt后,我们转移到$1文件并查找1在您的阵列中的存在。如果是,则评估为$1并打印该行。如果您的数组中不存在~,则它将评估为false并且不会打印该行。

上面的命令会查找完全匹配。我看到你使用了匹配运算符awk -F, 'NR==FNR{PATS[$0]++;next}{for(p in PATS) if($1~p) print $0}' b.txt a.txt ,这也意味着部分匹配。如果这就是你想要的,你可以做到:

{{1}}

如果这对您不起作用,我建议您从这两个文件中发布一些示例数据。

答案 1 :(得分:1)

如果你的shell是bash或ksh(或者zsh)

,这就是你想要的
grep -f <(sed 's/^/^/; s/$/,/' b.txt) a.txt