提高对大文件的grepping的性能


10

我有FILE_A有30万行,而FILE_B有3000万行。我创建了一个Bash脚本,将FILE_A中的每一行都移到FILE_B中,并将grep的结果写入新文件。

整个过程耗时超过5个小时。

如何提高脚本的性能?

我正在使用grep -F -m 1grep命令。FILE_A看起来像这样:

123456789 
123455321

FILE_B是这样的:

123456789,123456789,730025400149993,
123455321,123455321,730025400126097,

因此,对于Bash,我有一个while循环,可以在FILE_A中选择下一行,然后在FILE_B中进行抓取。在FILE_B中找到该模式后,我将其写入文件result.txt。

while read -r line; do
   grep -F -m1 $line 30MFile
done < 300KFile

Answers:


17

尝试使用grep --file==FILE_A。几乎可以肯定,它将模式加载到内存中,这意味着它将仅扫描FILE_B一次。

grep -F -m1 --file==300KFile 30MFile

仅在我有足够的内存的情况下才可以使用?
rogerio_marcio

老实说,我还没有尝试过使用这种大小的文件,但是我相信它可以大大提高您的速度。如果您使用的是现代计算机,则将300K文件保存在内存中应该没有问题。(或者30M一个对这一问题。)
戈特机器人

当我使用-f(--file)选项时,它基本上重新创建了30MFile。难道我做错了什么?
rogerio_marcio 2012年

嗯...也许300Kfile中有空行?
Gort机器人2012年

就在现场!就是这样!效果很好,它在30秒内完成!谢谢!!
rogerio_marcio 2012年

2

这是后代的Perl答案。我通常这样做是为了将1M线匹配到30-35M线。完成大约需要10秒钟。

首先,哈希FILE_A:

my %simple_hash;
open my $first_file, '<', 'FILE_A' or die "What have you done?! $!";
while (<$first_file>) {
  chomp;                 ## Watch out for Windows newlines
  $simple_hash{$_} = 1;  ## There may be an even faster way to define this
}
close $first_file;

然后,如果你的大文件的限制而知道后去什么样的列,检查只是存在散列键的,你跑下来FILE_B,这是多,多少不是检查是否相等或正则表达式匹配速度快:

open my $second_file, '<', 'FILE_B' or die "Oh no, not again.. $!";
while (<$second_file>) {
  my ($col1, undef) = split ',';
  if (exists($simple_hash{$col1}) {
    print $_;
  }
}
close $second_file;

如果较大的目标文件无法很好地解析,则此脚本会失去其价值,因为其速度的很大一部分来自不必启动正则表达式引擎。


1

如果您不介意更多涉及编程的问题,请考虑使用后缀树(或变体)。

您可以在线性时间内FILE_B使用Ukkonen算法进行预处理。然后,您可以FILE_A按时间查询线性的线长度,并获取所有匹配的线号(可能需要稍稍修改一下树),然后可以将其写入结果文件。

如果n是的长度FILE_BN是in的行数,FILE_Am是最长的in 的行的长度,则整个过程将在时间O(n + Nm)中FILE_A运行-这本质上是线性运行时。在数量上击败了原始方法所需的二次时间。


1

--mmap最近找到了该标志,没有机会对其进行测试,但是很高兴得知您的发现。这是手册页中的描述:

--mmap If  possible, use the mmap(2) system call to read input, instead
      of the default read(2) system call.  In some situations,  --mmap
      yields  better performance.  However, --mmap can cause undefined
      behavior (including core dumps) if an input file  shrinks  while
      grep is operating, or if an I/O error occurs.

请参见有关进一步信息mmap


我肯定会试一试,然后告诉您进展如何。我会遇到核心转储的可能性有多大?
rogerio_marcio 2012年

@rogerio_marcio好吧,据我了解的人说,“如果grep运行时文件缩小了,或者发生了I / O错误。” 不太可能,但是您应该对此有所了解。(如果我假设grep时文件未触及-则不会发生)
Ramzi Kahil 2012年

为了测试--mmap不会遗失任何东西,我建议运行--mmap,不运行。然后使用wc来查看您具有相同的输出量-考虑到我们运行了2倍grep,并且只是一个标志不同,所以这应该是一个可靠的测试。
拉姆齐·卡希尔

@rogerio_marcio您尝试过吗?有什么见解吗?
Ramzi Kahil 2012年

-1

你为什么不把那个文件放到数据库中呢,数据库真的很擅长这样高效的合并,哈希,嵌套循环连接。而且他们真的很善于利用虚拟内存


您使用其他所有答案所做的全部就是重新发明数据库轮子
Andyz Smith
By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.