Saya ingin mengekstrak semua log di antara dua cap waktu. Beberapa baris mungkin tidak memiliki timestamp, tapi saya juga ingin garis itu. Singkatnya, saya ingin setiap baris yang berada di bawah dua prangko waktu. Struktur log saya terlihat seperti:
[2014-04-07 23:59:58] CheckForCallAction [ERROR] Exception caught in +CheckForCallAction :: null
--Checking user--
Post
[2014-04-08 00:00:03] MobileAppRequestFilter [DEBUG] Action requested checkforcall
Misalkan saya ingin mengekstraksi semuanya antara 2014-04-07 23:00
dan 2014-04-08 02:00
.
Harap perhatikan stempel waktu mulai atau stempel waktu akhir mungkin tidak ada di log, tapi saya ingin setiap baris di antara kedua stempel waktu ini.
text-processing
sed
awk
grep
Amit
sumber
sumber
date -d
perintah dan menggunakannya untuk membangun pola pencarian.Jawaban:
Anda dapat menggunakan
awk
ini:Dimana:
-F
menentukan karakter[
dan]
sebagai pemisah bidang menggunakan ekspresi reguler$0
referensi satu baris lengkap$2
referensi bidang tanggalp
digunakan sebagai variabel boolean yang menjaga pencetakan aktual$0 ~ /regex/
benar jika regex cocok$0
>=
digunakan untuk membandingkan string secara leksikografis (setara dengan misalnyastrcmp()
)Variasi
Baris perintah di atas mengimplementasikan pencocokan interval waktu buka-kanan . Untuk mendapatkan semantik interval tertutup cukup tambahkan tanggal kanan Anda, misalnya:
Jika Anda ingin mencocokkan cap waktu dalam format lain, Anda harus memodifikasi
$0 ~ /^\[/
sub-ekspresi. Perhatikan bahwa ini digunakan untuk mengabaikan garis tanpa cap waktu dari logika on / off cetak.Misalnya untuk format cap waktu seperti
YYYY-MM-DD HH24:MI:SS
(tanpa[]
kawat gigi) Anda dapat memodifikasi perintah seperti ini:(perhatikan bahwa pemisah bidang juga diubah - ke transisi kosong / tidak kosong, default)
sumber
$1 ~ /^[0-9]{4}-[0-9]{2}-[0-9]{2}/ && $2 ~/[0-2][0-9]:[0-5][0-9]:[0-5][0-9]/ { Time = $1" "$2; if (Time >= "2014-04-07 23:00" ) { p=1 } if (Time >= "2014-04-08 02:00:01" ) { p=0 } } p
code
$ 0 ~ / ^ [az | AZ] {4} - [0-9] {2} - [0-9] {4} [0-2] [0-9 ]: [0-5] [0-9]: [0-5] [0-9] / && $ 1 "" $ 2> = "Apr-07-2014 11:00" {p = 1} $ 0 ~ / ^ [az | AZ] {4} - [0-9] {2} - [0-9] {4} [0-2] [0-9]: [0-5] [0-9]: [0 -5] [0-9] / && $ 1 "" $ 2> = "Apr-07-2014 12:00:01" {p = 0}code
tetapi tidak berfungsiLihat
dategrep
di https://github.com/mdom/dategrepDeskripsi:
Contoh penggunaan:
Meskipun batasan ini mungkin membuat ini tidak sesuai untuk pertanyaan persis Anda:
sumber
Salah satu alternatif
awk
atau alat non-standar adalah dengan menggunakan GNUgrep
untuk greps kontekstualnya. GNUgrep
akan membiarkan Anda menentukan jumlah garis setelah kecocokan positif untuk dicetak dengan-A
dan garis sebelumnya untuk mencetak dengan-B
Misalnya:Di atas pada dasarnya memberitahu
grep
untuk mencetak 10.000 baris yang mengikuti garis yang cocok dengan pola yang ingin Anda mulai, secara efektif membuat output Anda mulai di mana Anda ingin dan pergi sampai akhir (mudah-mudahan) sedangkan yang keduaegrep
di pipeline memberitahukannya untuk hanya mencetak garis dengan pembatas akhir dan 10.000 baris sebelumnya. Hasil akhir dari keduanya adalah mulai di mana Anda inginkan dan tidak akan berlalu di mana Anda menyuruhnya berhenti.10.000 hanya angka yang saya buat, jangan ragu untuk mengubahnya menjadi satu juta jika Anda berpikir output Anda akan terlalu lama.
sumber
sed
yang juga mencari kecocokan literal.dategrep
mungkin jawaban yang paling benar dari semua yang diberikan (karena Anda harus bisa mendapatkan "fuzzy" pada cap waktu apa yang akan Anda terima) tetapi seperti jawabannya, saya hanya menyebutkannya sebagai alternatif. Yang mengatakan, jika log cukup aktif untuk menghasilkan cukup output ke surat perintah pemotongan itu mungkin juga akan memiliki beberapa jenis entri untuk timeperiod diberikan.Menggunakan sed:
Salin ini dalam file. Jika Anda tidak ingin melihat info debug, debugging dikirim ke stderr jadi tambahkan saja "2> / dev / null"
sumber