Extraindo uma data de um arquivo de log e criando um arquivo com datas exclusivas

0

Gostaria de extrair de um arquivo a data com o formato DD.MM.YYYY , a data está sempre em primeiro lugar, aqui um exemplo das entradas

15.04.2016 13:13:30,228 INFO    [wComService] [mukumukuko@system/3] Call created with id:VoiceConnector$mukumukuko@system$D1:1:0:CB:SESSION$D1:1:0:DB:mukumukuko@system$D1:1:0:HB:_TARGET^M
15.04.2016 13:14:10,886 INFO    [wComService] Call 5303 from device +41999999999^M
15.04.2016 13:14:20,967 INFO    [AddressTranslatorService][mukumukuko@system/3] </convertLocalToGNF>^M
15.04.2016 13:14:20,992 INFO    [wComService] [mukumukuko@system/3] Call created with id: VoiceConnector$mukumukuko@system$D1:1:0:MB:SESSION$D1:1:0:NB:mukumukuko@system$D1:1:0:RB:_TARGET^M
15.04.2016 13:15:18,760 INFO    [OSMCService] SessionManager Thread - Heartbeat (1clients connected)^M

esse arquivo contém o registro de atividades de 1 semana, portanto, no arquivo, é possível encontrar datas, por exemplo, 16.04.2016 , 17.04.2016 , 18.04.2016 também.

O arquivo também pode ter essas saídas da exceção Java:

    at org.apache.xerces.impl.XMLNSDocumentScannerImpl.scanEndElement(Unknown Source)
    at org.apache.xerces.impl.XMLDocumentFragmentScannerImpl$FragmentContentDispatcher.dispatch(Unknown Source)
    at org.apache.xerces.impl.XMLDocumentFragmentScannerImpl.scanDocument(Unknown Source)
    at org.apache.xerces.parsers.XML11Configuration.parse(Unknown Source)
    at org.apache.xerces.parsers.XML11Configuration.parse(Unknown Source)

Eu tentei seguir:

cat fac.log | sed 's/^.*\([0-9]\{2\}.[0-9]\{2\}.[0-9]\{4\}\).*$//' > datesF1

mas eu entro em "datesF1" a data desejada, mas com essas mensagens de exceção Java

Então, o que eu gostaria é gerar um arquivo que exibe apenas datas exclusivas sem repeti-las, por exemplo, "datesF1" deve ser:

15.04.2016
16.04.2016
17.04.2016
18.04.2016

Você sabe se isso é possível ou se é melhor usar o comando grep?

    
por arexturicum 24.05.2016 / 16:49

2 respostas

0

O motivo pelo qual o comando sed não funciona é que ele pressupõe que você tenha uma data em todas as linhas, o que não é o caso se algumas linhas vierem de mensagens de erro de várias linhas. Quando não há nada que corresponda ao padrão de substituição, o sed não substitui e as listagens de pilha de chamadas que você viu permanecem na saída.

Para obter apenas as datas das linhas que as têm no começo, você tem várias opções:

grep:

grep -Eo '^[0-9.]+' fac.log 

-o diz ao grep para imprimir apenas a parte correspondente, em vez da linha inteira, e -E ativa expressões regulares "estendidas"

awk:

awk '/^[0-9.]+/ {print $1}' fac.log

A primeira parte do comando awk é uma correspondência de expressão regular, o resto é o que fazer com uma linha correspondente, aqui imprimimos a primeira palavra na linha.

Perl:

perl -lne 'print $1 if /^([0-9]+)/' fac.log

-l: imprime uma nova linha em cada print , -n: executa o comando para cada linha de entrada (como awk), -e: apenas informa que o programa é fornecido na linha de comando e não em um arquivo .

Em todos os casos, você obtém uma linha de saída por linha de entrada correspondente, ou seja, datas de repetição. Piping o resultado através de | sort | uniq é provavelmente o idioma mais simples para remover duplicatas.

Note que eu era preguiçoso e usei ^[0-9.]+ em vez do padrão mais longo e exato. Isso está relacionado ao motivo pelo qual eu gosto de usar o perl ao invés do sed, do awk e dos amigos: a expressão regular do Perl é sempre a mesma, independentemente do que você está fazendo. Também em Perl, não há necessidade de lembrar quais modificadores são suportados por padrão e quais requerem configuração -E ou o que for. Então há as diferenças entre as versões: aparentemente, meus sistemas Debian têm o mawk ao invés do GNU awk por padrão, e não parece suportar o modificador {N}, então o padrão mais exato não funcionou. Ops.

Manual do GNU awk: "As expressões de intervalo não estavam tradicionalmente disponíveis no awk. Elas foram adicionadas como parte do padrão POSIX para tornar o awk e o egrep consistentes entre si." (ref. link )

    
por 25.05.2016 / 15:28
0
awk '/^[0-9]{2}[.][0-9]{2}[.][0-9]{4}/ {DATES[$1]++} 
     END{ for(d in DATES) {print d} }'

Ao contrário do rock, do papel e da tesoura: o awk sempre bate no sed. :-)

Editar: aqui está em ação:

$ cut -b-60 t
15.04.2016 13:13:30,228 INFO    [wComService] [mukumukuko@sy
15.05.2016 13:14:10,886 INFO    [wComService] Call 5303 from
15.06.2016 13:14:20,967 INFO    [AddressTranslatorService][m
15.07.2016 13:14:20,992 INFO    [wComService] [mukumukuko@sy
15.04.2016 13:15:18,760 INFO    [OSMCService] SessionManager
this file contains the activity log of 1 week, so in the fil

The file can have also these outputs from Java exception:

    at org.apache.xerces.impl.XMLNSDocumentScannerImpl.scanE
    at org.apache.xerces.impl.XMLDocumentFragmentScannerImpl
    at org.apache.xerces.impl.XMLDocumentFragmentScannerImpl
    at org.apache.xerces.parsers.XML11Configuration.parse(Un
    at org.apache.xerces.parsers.XML11Configuration.parse(Un

$ awk '/^[0-9]{2}[.][0-9]{2}[.][0-9]{4}/ {DATES[$1]++} 
     END{ for(d in DATES) { print d } }' t
15.07.2016
15.06.2016
15.04.2016
15.05.2016

Isso é o GNU awk. Se sua versão do awk não produz saída, provavelmente é porque sua implementação de expressão regular é diferente e não corresponde a nenhuma linha. Pode não suportar chaves como um especificador de repetição, por exemplo. Com o custo da especificidade perdida, você pode simplificar a regex para /^[0-9]/ , o que definitivamente funcionará. Isso captura as datas e elimina as mensagens de log, mas também pode prender algumas não-datas.

Alguma experimentação e tempo com o seu manual de ajuda amigável pode ser proveitoso. ; -)

    
por 25.05.2016 / 02:44