Converter / substituir o tempo de milissegundos de época para data legível por humanos em arquivos de log
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
Se você usar um script de shell lendo linha por linha, ou um awk
sistema 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
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 gawk
soluçã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 strftime
função converte o carimbo de data / hora em uma data. Como o seu é em milissegundos, usamos sprintf
para convertê-lo em segundos. O final 1;
apenas informa gawk
para 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 TZ
variá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