Analisa um log usando perl

0

Estou procurando analisar um log usando um comando perl que eu projetei. Até agora, tudo que eu gostaria de realizar é obter um formato de registro de data e hora específico e recuperar o host. o log ficaria assim

2016-05-07T09:07:04.933343+00:00 heroku[router]: status=301 bytes=680 service=2698ms connect=1ms dyno=web.2 fwd="10.29.10.29" at=info host="jamaican.com" request_id=32fc8d88-99f8-4cc2-89f9-284d059eebf8 method=GET path="/blog"

meu comando pode analisar o formato de data que eu quero, mas eu não consigo descobrir como adicionar o host na saída. Quaisquer recomendações seriam excelentes!

cat test.log  |
perl -lne 'print $1 if  /^([0-9]+[-]+[0-9]+[0-9]+[-]+[0-9]+[0-9]+[T]+[0-9]+[0-9]+[:]+[0-9]+[0-9]+[:]+[0-9]+[0-9])/'
    
por Matthew Morcaldi 14.03.2018 / 05:58

2 respostas

3

Tente isto:

perl -nle'($time, $host) = /^(\S+)\s(?:\S+\s+){8}\S+="(\S+?)"/; print "$time $host"'

Saída:

2016-05-07T09:07:04.933343+00:00 jamaican.com
  • \S significa não espaço
  • \s é espaço
  • (?:) é um agrupamento lógico que não foi capturado
  • {8} são as "palavras" ignoradas
  • \S+="(\S+?)" significa: pule até = e capture o que há entre as duas " quotes
  • ($time, $host) = /.../ atribui os dois grupos capturados a $time e $host
por 14.03.2018 / 07:15
0

Você precisa capturar o nome do host com um segundo grupo de captura.

por exemplo. usando sua entrada de amostra:

$ cat test.log 
2016-05-07T09:07:04.933343+00:00 heroku[router]: status=301 bytes=680 service=2698ms connect=1ms dyno=web.2 fwd="10.29.10.29" at=info host="jamaican.com" request_id=32fc8d88-99f8-4cc2-89f9-284d059eebf8 method=GET path="/blog"

Esse perl one-liner extrai o registro de data e hora e o campo do nome do host. Eu melhorei o regex um pouco também, usando \d para dígitos, com uma contagem de correspondência para cada um.

$ perl -lne 'print "$1 $2" if (m/(\d{4}-\d{2}-\d{2}T\d{2}:\d{2}:\d{2}.\d+\+\d{2}:\d{2}) ([^ ]+) /)' test.log
2016-05-07T09:07:04.933343+00:00 heroku[router]:

Outra alternativa:

$ perl -lne 'print "$1 $2 $3" if (m/(\d{4}-\d{2}-\d{2}T\d{2}:\d{2}:\d{2}.\d+\+\d{2}:\d{2}) ([^[]+)\[([^]]+)\]/)' test.log
2016-05-07T09:07:04.933343+00:00 heroku router

Eu assumi que você queria o nome do host da máquina local (nem notei a parte host="jamaican.com" da entrada do log). Isso provavelmente não é o que você queria, então se você quiser o nome do host que está entre aspas duplas depois de host= , então:

$ perl -lne 'print "$1 $2" if (m/(\d{4}-\d{2}-\d{2}T\d{2}:\d{2}:\d{2}.\d+\+\d{2}:\d{2}).*host="([^"]+)"/)' test.log
2016-05-07T09:07:04.933343+00:00 jamaican.com 

ou (muito mais simples):

$ perl -lne 'print "$1 $2" if (m/(^\S+).*host="([^"]+)"/)' test.log
2016-05-07T09:07:04.933343+00:00 jamaican.com

Ou extraia o registro de data e hora, analise-o com Date::Parse e reformate-o com Date::Format .

$ perl -MDate::Parse -MDate::Format -lne \
  'if (m/(^\S+).*host="([^"]+)"/) {
     print join(" ", time2str("%Y-%m-%d %R %z",str2time($1)), $2)
   }' test.log
2016-05-07 19:07 +1000 jamaican.com

Observação: o registro de data e hora foi convertido para o fuso horário local (para mim, isso é +1000 ou o horário padrão da Austrália). time2str() usa o fuso horário local por padrão, mas você pode fornecer um terceiro argumento ( time2str(TEMPLATE, TIME [, ZONE]) ) para gerar a hora em qualquer outra zona.

$ perl -MDate::Parse -MDate::Format -lne   'if (m/(^\S+).*host="([^"]+)"/) {
     print join(" ", time2str("%Y-%m-%d %R %z",str2time($1),"+0"), $2)
   }' test.log
2016-05-07 09:07 +0000 jamaican.com
    
por 14.03.2018 / 07:09

Tags