Eu tenho um arquivo com cerca de 30.000.000 linhas (Radius Accounting) e preciso encontrar a última correspondência de um determinado padrão.
O comando:
tac accounting.log | grep $pattern
dá o que eu preciso, mas é muito lento porque o sistema operacional precisa primeiro ler o arquivo inteiro e depois enviar para o canal.
Então, preciso de algo rápido que possa ler o arquivo da última linha para a primeira.
fonte
tac
, o que quero dizer é que isso não ajuda, a menos que você também use,-m
pois o arquivo ainda precisa ser lido na íntegra por dois programas. Caso contrário, você poderia procurar todas as ocorrências e manter apenas a última, como eu façotail -n 1
.grep -m
, deve ser bastante eficiente.grep -m
ele. O OP não estava usando,-m
portanto, grep e tac estavam processando a coisa toda.awk
linha?A razão porque
não para na primeira partida é por causa do buffer.
Normalmente,
head -n 1
sai depois de ler uma linha. Portanto,grep
deve obter um SIGPIPE e sair assim que gravar sua segunda linha.Mas o que acontece é que, como sua saída não está indo para um terminal,
grep
ele é armazenado em buffer. Ou seja, ele não está gravando até que tenha acumulado o suficiente (4096 bytes no meu teste com o GNU grep).O que isso significa é que
grep
não será encerrado antes de gravar 8192 bytes de dados, portanto, provavelmente algumas linhas.Com o GNU
grep
, você pode fazê-lo sair mais cedo usando o--line-buffered
que diz para escrever linhas assim que forem encontradas, independentemente de ir para um terminal ou não. Então,grep
sairia na segunda linha que encontrar.Mas com o GNU de
grep
qualquer maneira, você pode usar-m 1
como o @terdon mostrou, o que é melhor quando ele sai na primeira partida.Se você
grep
não é o GNUgrep
, então você pode usarsed
ouawk
preferir. Mas,tac
sendo um comando GNU, duvido que você encontre um sistema emtac
quegrep
não seja o GNUgrep
.Alguns sistemas precisam
tail -r
fazer a mesma coisa que o GNUtac
.Observe que, para arquivos regulares (que podem ser procurados),
tac
etail -r
são eficientes porque eles lêem os arquivos para trás, eles não estão apenas lendo o arquivo completamente na memória antes de imprimi-lo para trás (como faria a abordagem sed do @ slm outac
em arquivos não regulares) .Em sistemas onde
tac
nemtail -r
existem nem estão disponíveis, as únicas opções são implementar a leitura reversa manualmente com linguagens de programação comoperl
ou usar:Ou:
Mas isso significa encontrar todas as correspondências e imprimir apenas a última.
fonte
Aqui está uma solução possível que encontrará a localização da primeira ocorrência do padrão desde a última:
Isso faz uso dos comutadores
-s
e-r
dostac
quais são os seguintes:fonte
Usando sed
Mostrando alguns métodos alternativos para a boa resposta de @ Terdon usando
sed
:Exemplos
Usando Perl
Como bônus, aqui está uma notação um pouco mais fácil no Perl:
Exemplo
fonte
sed
provável que essa seja (especialmente a ) várias ordens de magnitude mais lentas quegrep 5 | tail -n1
oused '/5/h;$!d;g'
. Também usará potencialmente muita memória. Não é muito mais portátil, pois você ainda está usando o GNUgrep -m
.