Reverter o grepping

43

Digamos que eu tenha um arquivo de texto muito grande (cerca de 10.000.000 linhas). Eu preciso grep do final e salvar o resultado em um arquivo. Qual é a maneira mais eficiente de realizar tarefas?

    
por chaos 23.07.2014 / 13:58

4 respostas

46

tac / grep Solução

tac file | grep whatever

Ou um pouco mais eficaz:

grep whatever < <(tac file)

Tempo com um arquivo de 500 MB:

real    0m1.225s
user    0m1.164s
sys     0m0.516s
Solução

sed / grep :

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

Tempo com um arquivo de 500 MB: interrompido após mais de 10 minutos.

Solução

awk / grep :

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

Tempo com um arquivo de 500 MB:

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

perl / grep Solução:

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

Tempo com um arquivo de 500 MB:

real    0m3.551s
user    0m3.104s
sys     0m1.036s
    
por 23.07.2014 / 14:26
17

Esta solução pode ajudar:

tac file_name | grep -e expression
    
por 23.07.2014 / 14:13
10

Este sai assim que encontra o primeiro jogo:

 tac hugeproduction.log | grep -m1 WhatImLookingFor

A seguir, as 5 linhas antes e depois das duas primeiras correspondências:

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

Lembre-se de não usar -i (insensível a maiúsculas e minúsculas) a menos que você tenha que diminuir o grep.

Se você souber a string exata que está procurando, considere fgrep (String Fixa)

 tac hugeproduction.log | grep -F -m2 -A 5 -B 5 'ABC1234XYZ'
    
por 23.07.2014 / 16:51
9

Se o arquivo for realmente grande, não cabe na memória, usarei Perl com File :: ReadBackwards de 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;

Então:

$ ./reverse-grep.pl pattern file
    
por 23.07.2014 / 19:00