Answers:
tac / 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
sed,awk和perl(使用此方法)不正确,因为它们从头开始读取文件,效率非常低。我认为这样tac做是对的。
< <(tac filename)应该与管道一样快:在两种情况下,命令都是并行运行的。
tacgrep 放在后面。如果您有一个10,000,000行的文件,并且只有2个匹配项,tac则只需要反转2行,而不是10m。grep无论如何,仍然需要经历整个过程。
tac之后grep,它将从管道读取,因此无法查找。如果找到的行数很多,这将使其效率降低(或完全失败)。
此解决方案可能会帮助:
tac file_name | grep -e expression
tac是GNU命令。在大多数其他系统上,等效项是tail -r。
tail -r限于少数行,这可能是一个问题。
tail -r /etc/passwd失败tail: invalid option -- 'r'。我正在使用coreutils-8.21-21.fc20.x86_64。
tac(只有GNU有tac)许多其他Unices都有tail -r。GNU tail不支持-r
如果文件确实很大,无法容纳在内存中,我将Perl与File :: ReadBackwards模块一起使用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
tac。
tac和grep实现您想要的。