Konwertuj / zamień czas z milisekund epoki na datę czytelną dla człowieka w plikach dziennika

Dec 05 2020

Mam plik dziennika o następującej strukturze

Przykład:

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

Teraz chciałbym zamienić czas z milisekund epoki na DD.MM.RRRR GG: MM: SS we wszystkich plikach dziennika poleceniem bash w systemie Debian.

Wypróbowałem różne rozwiązania dostarczone tutaj i na innych stronach internetowych, ale tak naprawdę nie działały.

Czy ktoś może mi pomóc, proszę?

Twoje zdrowie

fastboot

Odpowiedzi

4 thanasisp Dec 05 2020 at 22:13

Jeśli używasz skryptu powłoki czytającego wiersz po wierszu lub awksystemu wywołującego skrypt date, byłoby to bardzo powolne, zbyt wiele procesów. Musisz użyć prostego skryptu awk, Perl, Python lub czegokolwiek. Wszystkie języki mają standardowe funkcje daty i godziny do konwersji między formatami.

Tutaj i tutaj są dobre referencje. Jeśli chcesz korzystać z awk funkcji czasu GNU i strftime(), wszystko, czego potrzebujesz w swoim przypadku, to wybrać podciąg epoki z wyłączeniem milisekund:

$ 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

Lub wydrukować razem milisekundy:

$ 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

Lub wydrukować format dzień-miesiąc-rok:

$ 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

To nie jest coś, co możesz zrobić za pomocą polecenia bash, potrzebujesz zewnętrznego programu, ponieważ bash nie może wykonywać obliczeń zmiennoprzecinkowych i nie obsługuje dat. Podejrzewam, że miałeś na myśli po prostu „w wierszu poleceń” i tak naprawdę nie potrzebujesz czystego rozwiązania bash. Przy takim założeniu gawkmamy rozwiązanie (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

strftimeKonwertuje znacznik czasu do tej pory. Ponieważ twój jest w milisekundach, używamy go sprintfdo konwersji na sekundy. Ostateczna 1;po prostu mówi, gawkaby wydrukować wiersz po przypisaniu nowej wartości do $1(pierwszego pola).


Pamiętaj, że wynik będzie zależał od Twojej strefy czasowej. Na przykład powyższe zostało uruchomione na komputerze ustawionym na strefę czasową GMT. Dlatego moje liczby różnią się od tych w odpowiedzi @ thanasisp, która prawdopodobnie została uruchomiona w innej strefie czasowej. Możesz kontrolować to i zmienić wyjście, ustawiając TZzmienną podczas uruchamiania polecenia. Na przykład porównaj to:

$ 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

do tego:

$ 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

Albo to:

$ 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