Saya memiliki file yang berisi tanggal zaman yang perlu saya konversi agar dapat dibaca oleh manusia. Saya sudah tahu bagaimana melakukan konversi tanggal, misalnya:
[server01 ~]$ date -d@1472200700
Fri 26 Aug 09:38:20 BST 2016
..tapi saya berjuang untuk mencari cara sed
untuk berjalan melalui file dan mengkonversi semua entri. Format file terlihat seperti ini:
#1472047795
ll /data/holding/email
#1472047906
cat /etc/rsyslog.conf
#1472048038
ll /data/holding/web
text-processing
sed
date
masinis
sumber
sumber
HISTTIMEFORMAT
variabel shell untuk mengontrol format pada saat penulisan.date -d
tidak portabel untuk mengatakan Solaris ... Saya menganggap ini pada sistem dengan sebagian besar alat GNU? (GNU AWK / Perl cenderung menjadi metode yang lebih portabel untuk menangani konversi tanggal).gawk '{ if ($0 ~ /^#[0-9]*$/) {print strftime("%c",substr($0,2)); } else {print} }' < file
(strftime
sepertinya tidak bisa dibawa-bawa ...)Jawaban:
Dengan asumsi format file yang konsisten, dengan
bash
Anda dapat membaca file baris demi baris, uji apakah itu dalam format yang diberikan dan kemudian lakukan konversi:BASH_REMATCH
adalah array yang elemen pertama adalah grup yang ditangkap pertama kali dalam pencocokan Regex=~
,, dalam hal ini zaman.Jika Anda ingin mempertahankan struktur file:
ini akan menampilkan konten yang dimodifikasi ke STDOUT, untuk menyimpannya dalam file misalnya
out.txt
:Sekarang jika mau, Anda dapat mengganti file aslinya:
Contoh:
sumber
bash
,printf
dapat melakukan konversi itu sendiri:printf '#%(%F %H)T\n' "${BASH_REMATCH[1]}"
.Meskipun dimungkinkan dengan GNU
sed
dengan hal-hal seperti:Itu akan sangat tidak efisien (dan mudah untuk memperkenalkan kerentanan perintah injeksi sewenang-wenang 1 ) karena itu berarti menjalankan satu shell dan satu
date
perintah untuk setiap#xxxx
baris, hampir sama buruknya dengan shellwhile read
loop . Di sini, akan lebih baik menggunakan hal-hal sepertiperl
ataugawk
, yaitu utilitas pemrosesan teks yang memiliki kemampuan konversi tanggal bawaan:Atau:
1 Jika kita telah menulis
^#([0-9]).*
alih-alih^#([0-9]).*$
(seperti yang saya lakukan dalam versi sebelumnya dari jawaban ini), maka di multi-byte locales seperti UTF-8 (norma saat ini), dengan input like#1472047795<0x80>;reboot
, di mana itu<0x80>
adalah nilai byte 0x80 yang tidak membentuk karakter yang valid,s
perintah itu akhirnya akan berjalandate -d@1472047795<0x80>; reboot
misalnya. Sementara dengan tambahan$
, garis-garis itu tidak akan diganti. Suatu pendekatan alternatifs/^#([0-9])/date -d @\1 #/e
adalah:, yaitu meninggalkan bagian setelah#xxx
tanggal sebagai komentar shellsumber
date -f
untuk melakukan semua konversi secara stream-wise?s
flag menjadikannya.*
juga termasuk baris baru pada input. Anda juga bisa menggunakanstrftime "%c", localtime $1
.Semua jawaban lain menelurkan
date
proses baru untuk setiap tanggal yang perlu dikonversi. Ini berpotensi menambah overhead kinerja jika input Anda besar.Namun tanggal GNU memiliki
-f
opsi praktis yang memungkinkan instance proses tunggaldate
untuk terus membaca tanggal input tanpa perlu garpu baru. Jadi kita bisa menggunakansed
,paste
dandate
dengan cara ini masing-masing hanya akan muncul sekali (2x untuksed
) terlepas dari seberapa besar inputnya:sed
perintah tersebut masing-masing pada dasarnya menghapus garis genap dan ganjil dari input; yang pertama juga diganti#
dengan@
untuk memberikan format cap waktu zaman yang benar.sed
Output pertama kemudian disalurkan kedate -f
yang melakukan konversi tanggal yang diperlukan, untuk setiap baris input yang diterimanya.paste
. The<( )
konstruksi yang proses substitusi pesta yang efektif trick sisipkan ke dalam pemikiran itu adalah membaca dari nama file yang diberikan saat itu sebenarnya membaca output pipa dari dalam perintah.-d '\n'
memberitahupaste
untuk memisahkan garis keluaran ganjil dan genap dengan baris baru. Anda dapat mengubah (atau menghapus) ini jika misalnya Anda ingin cap waktu di baris yang sama dengan teks lainnya.Perhatikan bahwa ada beberapa GNUisme dan Bashisme dalam perintah ini. Ini bukan Posix-compliant dan seharusnya tidak diharapkan portabel di luar dunia GNU / Linux. Misalnya
date -f
melakukan sesuatu yang lain padadate
varian OSXes BSD .sumber
date -d
(dari pertanyaan) juga non-portabel ... (Pada FreeBSD akan mencoba mengacaukan pengaturan DST, pada Solaris akan memberikan kesalahan ...) Pertanyaannya tidak menentukan OS meskipun ...Dengan asumsi format tanggal yang Anda miliki di pos adalah yang Anda inginkan, regex berikut harus sesuai dengan kebutuhan Anda.
Perhatikan fakta bahwa ini hanya akan menggantikan satu zaman per baris.
sumber
sed: -e expression #1, char 48: invalid reference \3 on 's' command's RHS
menggunakan sed:
keluaran:
karena bahasa lokal saya adalah bahasa Arab :)
sumber
Solusi saya bagaimana melakukan itu di saluran pipa
sumber