たとえば、非常に大きなテキストファイル(約10.000.000行)があるとします。最後からgrep
して、結果をファイルに保存する必要があります。タスクを達成する最も効率的な方法は何ですか?
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
このソリューションは役立つかもしれません:
tac file_name | grep -e expression
これは、最初の一致が見つかるとすぐに終了します。
tac hugeproduction.log | grep -m1 WhatImLookingFor
以下は、最初の2つの一致の前後の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'
ファイルが本当に大きく、メモリに収まらない場合は、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