Ubah / ganti waktu dari masa milidetik ke tanggal yang dapat dibaca manusia di file log

Dec 05 2020

Saya memiliki file log dengan struktur berikut

Contoh:

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

Sekarang saya ingin mengganti waktu dari epoch milidetik menjadi DD.MM.YYYY HH: MM: SS di semua file log dengan perintah bash pada Sistem Debian.

Saya mencoba berbagai solusi yang disediakan di sini dan di situs web lain tetapi tidak benar-benar berhasil untuk saya.

Adakah yang bisa membantu saya?

Bersulang

fastboot

Jawaban

4 thanasisp Dec 05 2020 at 22:13

Jika Anda menggunakan pembacaan skrip shell baris demi baris, atau awksistem pemanggil skrip date, akan sangat lambat, terlalu banyak proses. Anda harus menggunakan awk sederhana, Perl, Python, atau apapun, script. Semua bahasa memiliki fungsi tanggal waktu standar untuk konversi antar format.

Berikut dan di sini adalah beberapa referensi yang baik. Jika Anda ingin menggunakan awk fungsi waktu GNU dan strftime(), yang Anda perlukan untuk kasus Anda adalah memilih substring epoch tidak termasuk milidetik:

$ 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

Atau untuk mencetak milidetik bersamaan:

$ 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

Atau untuk mencetak format hari-bulan-tahun:

$ 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

Ini bukanlah sesuatu yang dapat Anda lakukan dengan perintah bash, Anda memerlukan program eksternal karena bash tidak dapat melakukan matematika floating point dan tidak dapat menangani tanggal. Saya menduga Anda hanya bermaksud "pada baris perintah", dan Anda sebenarnya tidak memerlukan solusi bash murni. Dengan asumsi itu, inilah solusi gawk(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

The strftimeFungsi mengubah timestamp untuk kencan. Karena milik Anda dalam milidetik, kami menggunakan sprintfuntuk mengubahnya menjadi detik. Bagian terakhir 1;hanya memberi tahu gawkuntuk mencetak baris setelah kami menetapkan nilai baru ke $1(bidang pertama).


Ingatlah bahwa hasilnya akan tergantung pada zona waktu Anda. Misalnya, di atas dijalankan di mesin yang disetel ke zona waktu GMT. Inilah sebabnya mengapa nomor saya berbeda dengan yang ada di jawaban @ thanasisp yang mungkin dijalankan pada zona waktu yang berbeda. Anda dapat mengontrol ini dan mengubah output dengan mengatur TZvariabel saat menjalankan perintah. Misalnya, bandingkan ini:

$ 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

untuk ini:

$ 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

Atau ini:

$ 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