Warning: file_get_contents(/data/phpspider/zhask/data//catemap/4/unix/3.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Unix grep-f巨大文件的替代方案_Unix_Scripting_Grep_Large Files - Fatal编程技术网

Unix grep-f巨大文件的替代方案

Unix grep-f巨大文件的替代方案,unix,scripting,grep,large-files,Unix,Scripting,Grep,Large Files,file1是90MB(250万行,每行一个字) 文件2是45 Gb 不管我让它运行多长时间,该命令实际上不会产生任何结果。显然,这超出了grep的范围 grep似乎无法处理来自-f选项的那么多查询。但是,以下命令不会产生所需的结果: grep -F -f file1 file2 考虑到文件大小,我怀疑sed或awk是否是合适的替代方案 我对其他选择感到茫然。。。请帮忙。学习一些sql命令值得吗?容易吗?有人能给我指出正确的方向吗?我认为没有一个简单的解决办法 想象一下,您编写了自己的程序,该

file1是90MB(250万行,每行一个字)

文件2是45 Gb

不管我让它运行多长时间,该命令实际上不会产生任何结果。显然,这超出了grep的范围

grep似乎无法处理来自
-f
选项的那么多查询。但是,以下命令不会产生所需的结果:

grep -F -f file1  file2
考虑到文件大小,我怀疑sed或awk是否是合适的替代方案


我对其他选择感到茫然。。。请帮忙。学习一些
sql
命令值得吗?容易吗?有人能给我指出正确的方向吗?

我认为没有一个简单的解决办法

想象一下,您编写了自己的程序,该程序执行您想要的操作,最终将得到一个嵌套循环,其中外部循环迭代文件2中的行,内部循环迭代文件1(反之亦然)。迭代次数随着
size(file1)*size(file2)
的增加而增加。当两个文件都很大时,这将是一个非常大的数字。使用
head
缩小一个文件显然解决了这个问题,但代价是不再给出正确的结果

一种可能的解决方法是对其中一个文件进行索引(或排序)。如果您迭代file2,并且对于每个单词,您可以确定它是否在模式文件中,而不必完全遍历模式文件,那么您的情况会好得多。这假设您进行逐字比较。如果模式文件不仅包含完整单词,还包含子字符串,那么这将不起作用,因为对于文件2中的给定单词,您不知道在文件1中查找什么

学习SQL当然是个好主意,因为学习一些东西总是好的。它将永远不会解决您的问题,因为SQL将遭受上述相同的二次效应。如果索引适用于您的问题,它可能会简化索引

你最好的选择可能是退后一步,重新思考你的问题。

你可以试试。他们说它比grep快

您可以尝试:


Parallel还有许多其他有用的开关,可以加快计算速度。

尝试使用LC_ALL=C。它将搜索模式从UTF-8转换为ASCII,速度比原始速度提高140倍。我有一个26G的文件,这将需要我大约12个小时到几分钟。 资料来源:

所以我要做的是:

parallel --progress -a file1 'grep -F {} file2'
LC_ALL=C fgrep“模式”输出

Grep无法处理那么多的查询,而且在如此大的查询量下,修复使其速度慢得令人无法忍受的问题也无济于事

file1和file2是否每行由一个单词组成?这意味着您正在寻找精确的匹配项,我们可以使用
awk
快速完成这项工作:

awk'NR==FNR{query[$0]=1;next}query[$0]'file1 file2
NR(记录数,行号)仅等于第一个文件的FNR(特定于文件的记录数),我们在其中填充哈希,然后移到下一行。第二个子句检查其他文件中的行是否与散列中保存的行匹配,然后打印匹配的行

否则,您将需要迭代:

awk'NR==FNR{query[$0]=1;next}
{for(查询中的q)if(索引($0,q)){print;next}}'文件1文件2
我们不必仅仅检查散列,而必须循环检查每个查询,看看它是否与当前行匹配(
$0
)。这要慢得多,但不幸的是这是必要的(尽管我们至少在不使用正则表达式的情况下匹配普通字符串,所以可能会慢一些)。当我们有比赛时,循环停止

如果您确实希望将查询文件的行作为正则表达式计算,那么可以使用
$0~q
而不是更快的
索引($0,q)
。注意,这使用了,大致与
grep-E
egrep
相同,但没有(
{1,7}
)或for(
\b
)和(
\s
\w
等)


只要哈希值不超过
awk
可以存储的值,这些函数就可以工作。这可能低至2.1B个条目(基于最高32位有符号整数的猜测)或高至您的可用内存。

您可以使用
split
命令将文件1拆分为多个部分吗?SQL命令通常不会帮助您处理原始文件。@DanPichelman如果他将模式文件拆分为100个PC,他必须和45G怪物玩100次……这没关系……**并且**他必须删除重复的匹配线。因为grep-f是“或”。。。。我不知道它是否更快。你在运行什么操作系统?我使用
grep-F-F listFile
的经验是,您会收到一条错误消息,说
listFile太大了
(或类似)。陛下其他读者。。。是否有关于
-f listFile
作为排序文件的内容?此外,虽然SQL可以解决这个问题,但安装SQL、cfged等还需要很长的安装时间。如果您制定了一个定期运行的生产流程,这可能是值得的时间投资,但它可能不在您的项目时间表中。祝你好运你可以只做cat file2,因为如果你从一个文件中grep出250万字,几乎所有的行最终都会出现:)
parallel --progress -a file1 'grep -F {} file2'
LC_ALL=C fgrep "pattern" <input >output