Quero extrair todos os logs entre dois registros de data e hora. Algumas linhas podem não ter o carimbo de data / hora, mas também quero essas linhas. Em resumo, quero todas as linhas que caem sob dois carimbos de hora. Minha estrutura de log se parece com:
[2014-04-07 23:59:58] CheckForCallAction [ERROR] Exception caught in +CheckForCallAction :: null
--Checking user--
Post
[2014-04-08 00:00:03] MobileAppRequestFilter [DEBUG] Action requested checkforcall
Suponha que eu queira extrair tudo entre 2014-04-07 23:00
e 2014-04-08 02:00
.
Observe que o registro de data e hora de início ou o registro de data e hora de término podem não estar no log, mas quero todas as linhas entre esses dois registros de data e hora.
text-processing
sed
awk
grep
Amit
fonte
fonte
date -d
comando e usando-a para construir o padrão de pesquisa.Respostas:
Você pode usar
awk
para isso:Onde:
-F
especifica os caracteres[
e]
como separadores de campo usando uma expressão regular$0
referencia uma linha completa$2
referencia o campo de datap
é usado como variável booleana que protege a impressão real$0 ~ /regex/
é verdadeiro se regex corresponder$0
>=
é usado para comparar lexicograficamente a string (equivalente a, por exemplostrcmp()
)Variações
A linha de comando acima implementa a correspondência do intervalo de tempo de abertura à direita . Para obter semânticas de intervalo fechado, apenas incremente sua data correta, por exemplo:
Caso deseje corresponder os carimbos de data e hora em outro formato, você deve modificar a
$0 ~ /^\[/
subexpressão. Observe que ele costumava ignorar linhas sem nenhum registro de data e hora da lógica de ativação / desativação da impressão.Por exemplo, para um formato de carimbo de data e hora como
YYYY-MM-DD HH24:MI:SS
(sem[]
chaves), você pode modificar o comando da seguinte maneira:(observe que também o separador de campos foi alterado - para transição em branco / não em branco, o padrão)
fonte
$1 ~ /^[0-9]{4}-[0-9]{2}-[0-9]{2}/ && $2 ~/[0-2][0-9]:[0-5][0-9]:[0-5][0-9]/ { Time = $1" "$2; if (Time >= "2014-04-07 23:00" ) { p=1 } if (Time >= "2014-04-08 02:00:01" ) { p=0 } } p
code
$ 0 ~ / ^ [az | AZ] {4} - [0-9] {2} - [0-9] {4} [0-2] [0-9 ]: [0-5] [0-9]: [0-5] [0-9] / && $ 1 "" $ 2> = "07/04/04 - 11:00" {p = 1} $ 0 ~ / ^ [az | AZ] {4} - [0-9] {2} - [0-9] {4} [0-2] [0-9]: [0-5] [0-9]: [0 -5] [0-9] / && $ 1 "" $ 2> = "07/04/04 - 12:00:01" {p = 0}code
mas não está funcionandoConfira
dategrep
em https://github.com/mdom/dategrepDescrição:
Exemplos de uso:
Embora essa limitação possa torná-lo inadequado para sua pergunta exata:
fonte
Uma alternativa
awk
ou uma ferramenta não-padrão é usar o GNUgrep
para seus greps contextuais. Os GNUsgrep
permitem especificar o número de linhas após uma correspondência positiva para imprimir-A
e as linhas anteriores para imprimir.-B
Por exemplo:O acima diz essencialmente
grep
para imprimir as 10.000 linhas que seguem a linha que corresponde ao padrão em que você deseja iniciar, efetivamente fazendo sua saída começar onde você deseja e ir até o final (espero), enquanto a segundaegrep
no o pipeline diz para imprimir apenas a linha com o delimitador final e as 10.000 linhas antes dele. O resultado final desses dois está começando onde você está querendo e não passa onde você disse para parar.10.000 é apenas um número que inventei, fique à vontade para alterá-lo para um milhão, se você acha que sua produção será muito longa.
fonte
sed
que também está procurando correspondências literais.dategrep
é provavelmente a resposta mais correta de todas as respostas dadas (já que você precisa ser "confuso" com relação aos carimbos de data e hora que você aceita), mas, como diz a resposta, eu apenas a mencionei como alternativa. Dito isto, se o log estiver ativo o suficiente para gerar saída suficiente para garantir o corte, provavelmente também haverá algum tipo de entrada para o período de tempo especificado.Usando sed:
Copie isso em um arquivo. Se você não deseja ver as informações de depuração, a depuração é enviada para o stderr; basta adicionar "2> / dev / null"
fonte