リバースのインポート

リバースのインポート

非常に大きなテキストファイル(約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 -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

以下に、最初の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'

答え4

ファイルが本当に大きくてメモリに収まらない場合は、次Perlのように使用します。ファイル::戻るモジュール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

関連情報