grep -f巨大文件的替代品

时间:2013-05-02 17:04:09

标签: unix scripting grep large-files

grep -F -f file1  file2

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

file2是45 Gb

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

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

head file1  >  file3
grep -F -f file3   file2

考虑到文件大小,我怀疑sed或awk是否适合作为替代品。

我不知道其他选择......请帮助。学习一些sql命令是否值得?这简单吗?有人能指出我正确的方向吗?

4 个答案:

答案 0 :(得分:13)

尝试使用LC_ALL = C.它将搜索模式从UTF-8转换为ASCII,速度提高了原始速度的140倍。我有一个26G的文件,这需要我大约12个小时才能完成几分钟。 资料来源:Grepping a huge file (80GB) any way to speed it up?

所以我所做的是:

LC_ALL=C fgrep "pattern" <input >output

答案 1 :(得分:5)

我认为没有一个简单的解决方案。

想象一下,您编写自己的程序,它可以完成您想要的任务,最终会得到一个嵌套循环,其中外部循环遍历file2中的行,内部循环遍历file1(反之亦然)。迭代次数随size(file1) * size(file2)的增长而增长。当两个文件都很大时,这将是一个非常大的数字。使用head缩小一个文件显然可以解决此问题,但代价是不再提供正确的结果。

可能的出路是索引(或排序)其中一个文件。如果你遍历file2并且对于每个单词你可以确定它是否在模式文件中而不必必须完全遍历模式文件,那么你会好得多。这假设您进行逐字比较。如果模式文件不仅包含完整的单词,还包含子字符串,那么这将不起作用,因为对于file2中的给定单词,您不知道在file1中要查找的内容。

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

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

答案 2 :(得分:4)

您可以尝试ack。他们说它比grep更快。

您可以尝试parallel

parallel --progress -a file1 'grep -F {} file2'

Parallel有许多其他有用的开关可以更快地进行计算。

答案 3 :(得分:0)

Grep无法处理那么多查询,而且在该卷上,通过修复使grep -f bug变得如此难以忍受的速度而无法帮助它。

file1和file2都是每行一个单词组成的吗?这意味着您正在寻找完全匹配,我们可以使用# controllers/messages_controller.rb class MessagesController < ApplicationController def create client = Twilio::REST::Client.new(account_sid, auth_token) message = client.account.messages.create(:body => "Hello from Ruby", :to => params[:phoneNumber], :from => "+15555555555") render :json => { :sid => message.sid } end end # config/routes.rb ... resources :messages 快速完成:

awk

NR(记录数,行号)仅等于第一个文件的FNR(特定于文件的记录数),我们填充哈希值然后移到下一行。第二个子句检查其他文件是否与我们的哈希中保存的行匹配,然后打印匹配的行。

否则,您需要迭代:

awk 'NR == FNR { query[$0] = 1; next } query[$0]' file1 file2

我们不必仅仅检查哈希,而是遍历每个查询并查看它是否与当前行(awk 'NR == FNR { query[$0]=1; next } { for (q in query) if (index($0, q)) { print; next } }' file1 file2 )匹配。这是很多慢,但不幸的是必要(虽然我们至少匹配普通字符串而不使用正则表达式,所以它可能会更慢)。当我们有匹配时,循环停止。

如果您确实想要将查询文件的行评估为正则表达式,则可以使用$0而不是更快的$0 ~ q。请注意,这使用的是POSIX extended regular expressions,与index($0, q)grep -E大致相同,但没有bounded quantifiersegrep)或GNU extensions word boundaries{1,7})和shorthand character classes\b\s等)。

只要哈希不超过\w可以存储的内容,这些就应该有效。这可能低至2.1B条目(基于最高32位有符号int的猜测)或高达可用内存。