Eu tenho um arquivo de log de 8 Gb (log de produção do Rails). Eu preciso cortá-lo entre algumas datas (linhas). Qual comando eu poderia usar para fazer isso?
sed
será fácil.
Eu tenho um arquivo de log de 8 Gb (log de produção do Rails). Eu preciso cortá-lo entre algumas datas (linhas). Qual comando eu poderia usar para fazer isso?
sed
será fácil.
Respostas:
Algo como
sed '1,/last date prior to chunk/d;/first date after chunk/,$d' logfile | tee cut-log | less
tee cut-log
permite ver na tela o que está sendo colocado no arquivo cut-log
.
EDITAR:
Para satisfazer os padrões exigentes de fred.bear, aqui está uma solução sed (embora a solução awk seja muito mais bonita):
b=BB; e=EE ;echo -e "AA\nAA\nBB\nBB\nCC\nCC\nDD\nDD\nEE\nEE\nFF\nFF" | sed -n ":b;/$b/b p;n;b b;:p;p;n;/$e/b e;b p;:e;p;n;/$e/b e;q"
sed
pode corresponder awk
à velocidade, e na verdade foi um pouco mais rápido.
Para imprimir tudo entre FOO e BAR inclusive, tente:
$ sed -n '/FOO/,/BAR/p' file.txt
Isso fará o que você deseja ...
Tanto a inclusão quanto a exclusão das datas dos parâmetros são mostradas.
# set Test args
set 2011-02-24 2011-02-26 "junk"
from="$1"
till="$2"
file="$3"
# EITHER ==== +++++++++
# Ouptut lines between two parameter dates INCLUDING the parameter dates
awk -v from=$from -v till=$till '
($2 >= from) && ($2 <= till) { print $0 ; next }
($2 > till) { exit }' "$file"
# OR ======== ---------
# Ouptut lines between two parameter dates EXCLUDING the parameter dates
awk -v from=$from -v till=$till '
($2 > from) && ($2 < till) { print $0 ; next }
($2 >= till) { exit }' "$file"
Ele testa uma data (classificada) no campo 2 ... Aqui está um exemplo dos dados de teste
98 2011-02-05 xxxx
99 2011-02-05 xxxx
100 2011-02-06 xxxx
101 2011-02-06 xxxx
E aqui está o gerador de dados de teste .
awk -v from="$from" -v till="$till" '($2 >= from) { if ($2 <= till) { print } else { exit }' "$file"
if
instrução extra no total (nem mesmo uma por linha), ou seja. o fluxo lógico é efetivamente o mesmo, e a diferença no tempo de execução seria contada em nanossegundos .... A única razão pela qual não usei "else" é que esse é efetivamente meu primeiro awk
script de todos os tempos (além de um dia 4 anos atrás, quando brinquei com alguns exemplos) ... e esse é o primeiro mecanismo de ramificação viável que encontrei ... (e como mencionado. é tão rápido) .. Eu uso generosamente o sed
Tryq
Se no seu arquivo de log você tiver as datas nesse formato YYYY-MM-DD
, para encontrar todas as entradas, por exemplo, 10/02/2011, você pode:
grep 2011-02-10 log_file
Agora, digamos, se você deseja localizar as entradas para 2011-02-10 e 2011-02-11, use novamente, grep
mas com vários padrões:
grep -E '2011-02-10|2011-02-11' log_file
grep
irá procurar o arquivo inteiro, mesmo se a data gama está no início do arquivo. Em média, isso duplica o tempo de uma pesquisa, quando comparado a "sair após o último item do intervalo" ... Estou apenas me referindo a isso por causa do tamanho do arquivo de 8 GB mencionado na pergunta Os resultados do tempo de grep são quase idênticos ao exemplo sed aqui (1min 58seg). Aqui está o link para os resultados dos meus testes de tempo: paste.ubuntu.com/573477
Trabalhar com esse tamanho de arquivo é sempre difícil.
Um caminho a seguir poderia ser dividir esse arquivo em alguns pequenos; para isso, você pode usar o comando split.
split -d -l 50000 ToBigFile.data file_
Mesmo que esteja dividido, você ainda pode trabalhar com o arquivo como se fosse um usando um loop bash for
for f in `ls file_*`; do cat $f; done;
Mas, em vez do gato, você pode usar grep invertido para se livrar de dados indesejados, o que é irrelevante para isso. (ou o tipo de refinamento necessário).
Nesse ponto, você trabalhará apenas com muitos arquivos menores, e os comandos mencionados acima funcionarão em muitos arquivos menores.
E quando terminar, você pode usar um segundo for loop para criar o novo arquivo menor novamente.
for f in `ls file_*`; do cat $f >> NewFile.data ; done;
Atualização Desde que começamos a dividir os dados em vários arquivos, haverá muito trabalho com o disco rígido e isso leva tempo. (Nesta questão, aparentemente, 5min).
Por outro lado, os próximos passos provavelmente seriam mais rápidos.
Portanto, esse método provavelmente não faz sentido para uma operação simples grep, awk, sed, mas se os padrões de pesquisa se tornarem mais complicados, poderão se tornar mais rápidos.
perl -wlne '/^2011-02-24/ .. /^2011-02-25/ and print' log_file