我有一个通过原创者(dowork.sh独创者)工作的操作,并让您知道它在cleaned1中完成了什么。cleaned1的排序与原创者不同。我需要生成一个列表,列出dowork.sh需要处理的内容。本质上: list cleanedR - list cleaned1 = list cleaned2。这是个减运算。我发现可以使用以下grep选项执行该操作:
# wc -l cleaned*
9157094 cleaned1
14283591 cleanedR
# du -sh cleaned*
1.3G cleaned1
2.0G cleanedR
# grep -Fvf cleaned1 originallist > cleaned2运行5分钟,消耗42G或更少的内存,但是很多,然后退出失败;cleaned2是0字节长。
最后的cleaned2应该是14283591 - 9157094 = 5126497行长。
这是执行这种操作的正确语法(我用一个10行长的cleanedR和一个3行长的cleaned1测试了它,得到的cleaned2是7行),但是它消耗了大量的ram。是否有办法使grep不用消耗这么多内存来完成这项工作?我知道这需要一段时间,但我不介意。
我正在寻找类似排序的-T选项,它允许您不使用/tmp (在我的例子中是ram),并允许您使用另一个目录
sort -h
-T, --temporary-directory=DIR use DIR for temporaries, not $TMPDIR or /tmp;
multiple options specify multiple directories发布于 2017-08-16 22:51:01
sort命令对处理大型数据集有一些特定的支持,因为这是一个相对常见的用例。巨大的grep模式是一个非常罕见的用例,因此您不能期望开发人员在它上投入大量的精力。
如果行的顺序并不重要,那么您可以对这两个文件进行排序,然后可以对它们进行比较,而不需要每次在内存中存储超过几行,不管文件的长度如何。因为排序可以处理不适合内存的文件,所以这是有效的。
sort originallist >originallist.sorted
sort cleaned1 | comm -23 originallist.sorted - >cleaned2.sorted如果原件的顺序有问题,您可以在其中添加行号:
nl -w 22 originallist >originallist.numbered
# then generate cleaned1 from the numbered list因为originallist.numbered是排序的,所以您可以在它上运行comm来检测公共行。
如果订单很重要,而且对行进行编号已经太晚了,那么您可以尝试将cleaned1分割成块,并对每个块进行一次originallist传递。与最近的GNU分裂:
cp originalfile cleaned2.in
split -l 1000000 --filter='grep -Fxv -f - cleaned2.in >cleaned2.out; mv cleaned2.out cleaned2.in' cleaned1
mv cleaned2.in cleaned2(请注意,F不执行“全行匹配”,而是执行子字符串匹配。对于完整的字符串匹配,还需要-x。)
https://unix.stackexchange.com/questions/386306
复制相似问题