Converter / substituir o tempo de milissegundos de época para data legível por humanos em arquivos de log

Dec 05 2020

Eu tenho um arquivo de log com a seguinte estrutura

Exemplo:

1522693524403 entity1,sometext
1522693541466 entity2,sometext
1522693547273 entity1,sometext
...

Agora eu gostaria de substituir o tempo de milissegundos de época para DD.MM.AAAA HH: MM: SS em todos os arquivos de log por um comando bash em um sistema Debian.

Tentei diferentes soluções fornecidas aqui e em outros sites, mas realmente não funcionou para mim.

Alguém pode me ajudar por favor?

Felicidades

inicialização rápida

Respostas

4 thanasisp Dec 05 2020 at 22:13

Se você usar um script de shell lendo linha por linha, ou um awksistema de chamada de script date, seria muito lento, muitos processos. Você tem que usar um script awk, Perl, Python ou qualquer coisa simples. Todas as linguagens têm funções datetime padrão para conversões entre formatos.

Aqui e aqui estão algumas boas referências. Se você quiser usar as awk funções de tempo GNU e strftime(), tudo o que você precisa para o seu caso é selecionar a substring epoch excluindo os milissegundos:

$ awk '{$1 = strftime("%F %T", substr($1,1,10))} 1' file
2018-04-02 21:25:24 entity1,sometext
2018-04-02 21:25:41 entity2,sometext
2018-04-02 21:25:47 entity1,sometext

Ou para imprimir os milissegundos juntos:

$ awk '{$1 = strftime("%F %T", substr($1,1,10)) "." substr($1,11)} 1' file
2018-04-02 21:25:24.403 entity1,sometext
2018-04-02 21:25:41.466 entity2,sometext
2018-04-02 21:25:47.273 entity1,sometext

Ou para imprimir o formato dia-mês-ano:

$ awk '{$1 = strftime("%d-%m-%Y %T", substr($1,1,10))} 1' file
02-04-2018 21:25:24 entity1,sometext
02-04-2018 21:25:41 entity2,sometext
02-04-2018 21:25:47 entity1,sometext
2 terdon Dec 05 2020 at 22:14

Isso não é algo que você pode fazer com um comando bash, você precisa de um programa externo, pois o bash não pode fazer matemática de ponto flutuante e não pode lidar com datas. Suspeito que você quis dizer apenas "na linha de comando" e não precisa de uma solução bash pura. Com essa suposição, aqui está uma gawksolução (GNU awk):

$ gawk '{$1=strftime("%d.%m.%Y %H:%m:%S",sprintf("%.3f", $1 /1000))}1;' file
02.04.2018 19:04:24 entity1,sometext
02.04.2018 19:04:41 entity2,sometext
02.04.2018 19:04:47 entity1,sometext

A strftimefunção converte o carimbo de data / hora em uma data. Como o seu é em milissegundos, usamos sprintfpara convertê-lo em segundos. O final 1;apenas informa gawkpara imprimir a linha após atribuirmos o novo valor a $1(o primeiro campo).


Lembre-se de que a saída dependerá do seu fuso horário. Por exemplo, o código acima foi executado em uma máquina configurada para o fuso horário GMT. É por isso que meus números são diferentes dos da resposta de @ thanasisp, que presumivelmente foi executada em um fuso horário diferente. Você pode controlar isso e alterar a saída definindo a TZvariável ao executar o comando. Por exemplo, compare isto:

$ gawk '{$1=strftime("%d.%m.%Y %H:%m:%d.%S",sprintf("%.3f", $1 /1000))}1;' file
02.04.2018 19:04:02.24 entity1,sometext
02.04.2018 19:04:02.41 entity2,sometext
02.04.2018 19:04:02.47 entity1,sometext

para isso:

$ TZ=America/Los_Angeles gawk '{$1=strftime("%d.%m.%Y %H:%m:%d.%S",sprintf("%.3f", $1 /1000))}1;' file
02.04.2018 11:04:02.24 entity1,sometext
02.04.2018 11:04:02.41 entity2,sometext
02.04.2018 11:04:02.47 entity1,sometext

Ou isto:

$ TZ=Asia/Tokyo gawk '{$1=strftime("%d.%m.%Y %H:%m:%d.%S",sprintf("%.3f", $1 /1000))}1;' file
03.04.2018 03:04:03.24 entity1,sometext
03.04.2018 03:04:03.41 entity2,sometext
03.04.2018 03:04:03.47 entity1,sometext