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)
应该与管道一样快:在两种情况下,命令都是并行运行的。
tac
grep 放在后面。如果您有一个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
实现您想要的。