反向抓取

反向抓取

假设我有一个非常大的文本文件(大约 10.000.000 行)。我需要grep从最后开始并将结果保存到文件中。完成任务最有效的方法是什么?

答案1

塔克/grep解决方案

tac file | grep whatever

或者更有效一点:

grep whatever < <(tac file)

处理 500MB 文件的时间:

real    0m1.225s
user    0m1.164s
sys     0m0.516s

sed/grep解决方案:

sed '1!G;h;$!d' | grep whatever

处理 500MB 文件的时间:10 多分钟后中止。

awk/grep解决方案:

awk '{x[NR]=$0}END{while (NR) print x[NR--]}' file | grep whatever

处理 500MB 文件的时间:

real    0m5.626s
user    0m4.964s
sys     0m1.420s

Perl/grep解决方案:

perl -e 'print reverse <>' file | grep whatever

处理 500MB 文件的时间:

real    0m3.551s
user    0m3.104s
sys     0m1.036s

答案2

该解决方案可能会有所帮助:

tac file_name | grep -e expression

答案3

这个一旦找到第一个匹配就退出:

 tac hugeproduction.log | grep -m1 WhatImLookingFor

下面给出了前两场比赛前后的 5 行:

 tac hugeproduction.log | grep -m2 -A 5 -B 5 WhatImLookingFor

记住不要使用-i(不区分大小写),除非你必须这样做,因为这会减慢 grep 的速度。

如果您知道要查找的确切字符串,请考虑fgrep(固定字符串)

 tac hugeproduction.log | grep -F -m2 -A 5 -B 5 'ABC1234XYZ'

答案4

如果文件真的很大,内存无法容纳,我将使用Perlwith文件::向后读模块来自CPAN

$ cat reverse-grep.pl
#!/usr/bin/perl

use strict;
use warnings;

use File::ReadBackwards;

my $pattern = shift;
my $rev = File::ReadBackwards->new(shift)
    or die "$!";

while (defined($_ = $rev->readline)) {
    print if /$pattern/;
}

$rev->close;

然后:

$ ./reverse-grep.pl pattern file

相关内容