一小段Perl代码解决了该问题。这是采取的方法:
- 将的行存储
file1.txt
在哈希中 file2.txt
逐行读取,解析并提取第二个字段- 检查提取的字段是否在哈希中;如果是这样,打印行
这是代码:
#!/usr/bin/perl -wuse strict;if (scalar(@ARGV) != 2) { printf STDERR "Usage: fgrep.pl smallfile bigfilen"; exit(2);}my ($small_file, $big_file) = ($ARGV[0], $ARGV[1]);my ($small_fp, $big_fp, %small_hash, $field);open($small_fp, "<", $small_file) || die "Can't open $small_file: " . $!;open($big_fp, "<", $big_file) || die "Can't open $big_file: " . $!;# store contents of small file in a hashwhile (<$small_fp>) { chomp; $small_hash{$_} = undef;}close($small_fp);# loop through big file and find matcheswhile (<$big_fp>) { # no need for chomp $field = (split(/|/, $_))[1]; if (defined($field) && exists($small_hash{$field})) { printf("%s", $_); }}close($big_fp);exit(0);我使用file1.txt中的14K行和file2.txt中的130M行运行了上述脚本。它在大约13秒内完成了126K场比赛。这是
time相同的输出:
real 0m11.694suser 0m11.507ssys 0m0.174s
我运行了@Inian的
awk代码:
awk 'FNR==NR{hash[$1]; next}{for (i in hash) if (match($0,i)) {print; break}}' file1.txt FS='|' file2.txt它比Perl解决方案慢得多,因为它使file2.txt中的每一行循环14K次-
这确实很昂贵。它在处理了592K条记录
file2.txt并产生了40K条匹配的线后中止。这是花了多长时间:
awk: illegal primary in regular expression 24/Nov/2016||592989 at 592989 input record number 675280, file file2.txt source line number 1real 55m5.539suser 54m53.080ssys 0m5.095s
使用@Inian的其他
awk解决方案可以消除循环问题:
time awk -F '|' 'FNR==NR{hash[$1]; next}$2 in hash' file1.txt FS='|' file2.txt > awk1.outreal 0m39.966suser 0m37.916ssys 0m0.743stime LC_ALL=C awk -F '|' 'FNR==NR{hash[$1]; next}$2 in hash' file1.txt FS='|' file2.txt > awk.outreal 0m41.057suser 0m38.475ssys 0m0.904sawk鉴于我们不必编写整个程序来做到这一点,因此在这里给人留下了深刻的印象。
我也运行了@oliv的Python代码。完成这项工作大约花了15个小时,看起来效果不错。构建大型正则表达式的效率不及使用哈希查找的效率。这里的
time输出:
real 895m14.862suser 806m59.219ssys 1m12.147s
我试图按照建议使用parallel。但是,
fgrep:memory exhausted即使块大小很小,它也会因错误而失败。
令我惊讶的是,这
fgrep完全不适合这样做。22小时后我终止了它,并产生了约10万次匹配。 我希望
fgrep有一个选项可以强制将其内容
-ffile保留在哈希中,就像Perl代码所做的那样。
我没有检查
join方法-我不需要排序文件的额外开销。而且,由于
fgrep性能不佳,我认为
join这样做不会比Perl代码更好。
感谢大家的关注和回应。



