Cetak baris hanya jika baris berikutnya TIDAK mengandung kecocokan tertentu


12

Saya mencoba mencari file log untuk aktivitas log yang tidak lengkap. Misalnya, saya mencatat "Aktivitas awal untuk ID 1234 ..." dan jika berhasil, baris berikutnya adalah "Aktivitas 1234 Selesai."

Saya mencoba mendapatkan garis "Mulai ..." yang TIDAK diikuti oleh garis "Selesai" yang sesuai.

Contoh File Log

Starting activity for ID 1234
ID 1234 completed successfully
Starting activity for ID 3423
ID 3423 completed successfully
Starting activity for ID 9876
ID 9876 completed successfully
Starting activity for ID 99889
ID 99889 completed successfully
Starting activity for ID 10011
ID 10011 completed successfully
Starting activity for ID 33367
Starting activity for ID 936819
ID 936819 completed successfully

Dalam contoh ini, saya akan mencari output menjadi:

Starting activity for ID 33367

... karena tidak diikuti oleh garis "selesai".

Saya sudah mencoba melakukan ini dengan grepdan awk, tetapi belum banyak berhasil. Saya berasumsi itu bisa dilakukan dengan salah satu alat itu, tetapi saya grepdan awkdaging tidak maju.

Mencari pola grepatau cepat dan dapat diandalkan awkuntuk memberikan hasil yang saya butuhkan di sini.


Saya tidak berpikir itu mudah dengan grep + awk, tetapi dapatkah Anda menjelaskan sedikit tentang mengapa Anda melakukan itu? Keluaran dari semua kegiatan yang berjalan, mis sukses atau tidak finsihed?
Daisy

@ warl0ck, saya mencari "belum selesai".
PattMauler

Jawaban:


10

Berikut ini sebuah awkalternatif:

awk '
  /^Starting/ { I[$5] = $0                  }
  /^ID/       { delete I[$2]                }
  END         { for (key in I) print I[key] }
' infile

Keluaran:

Starting activity for ID 33367

The Iarray asosiatif melacak apa id telah terlihat.


Ini berfungsi dengan sangat baik, karena tampaknya mengakomodasi situasi di mana baris log "Mulai ..." dan "Selesai ..." tidak berdekatan / berurutan. Terima kasih @Thor!
PattMauler

Sama-sama. Ini harus bekerja secara efisien dengan (hampir) input ukuran sewenang-wenang karena hanya menyimpan ID dan waktu pencarian adalah O (1).
Thor

Bagus. Hanya satu hal: seperti yang saya pelajari dari @RobertL ( unix.stackexchange.com/a/243550/135943 ) Anda tidak perlu menetapkan nilai untuk membuat elemen array. Jadi alih-alih I[$5] = 1, Anda bisa menggunakannya I[$5]. (Anda tidak peduli dengan nilainya, Anda hanya ingin membuat elemen itu ada , dan cukup menamainya.)
Wildcard

@Wildcard: Anda benar, tetapi setelah meninjau pertanyaan OP dan output grep like yang dia kejar, lebih tepat untuk mengingat seluruh baris dan output yang ada di akhir.
Thor

3
sed '$!N;/\n.*completed/d;P;D' <input

Ini akan menghapus dari output semua jalur input yang tidak diikuti oleh garis yang cocok dengan string yang selesai .


2

Inilah cara Anda dapat melakukannya dengan sed GNU:

sed -r 'N; /([0-9]+)\n\w+\s+\1/d; P; D' infile
  • N membaca satu baris lagi ke dalam ruang pola.
  • Regex pertandingan memeriksa apakah id identik ditemukan, jika demikian ruang pola dihapus ( d) dan siklus dimulai kembali.
  • Jika tidak cocok, cetak baris pertama dalam ruang pola ( P) dan hapus ( D).

Saya tidak bisa melihat apa-apa diperpanjang di sini ... jadi -rtidak diperlukan, kan?
Louis Maddox

1
@ lmmx: Ini diperlukan karena jika tidak, grup tangkap perlu melarikan diri, dan hal yang sama berlaku untuk +kuantifier.
Thor

Ah baiklah! Saya memodifikasinya dan diberitahu bahwa itu tidak perlu, terima kasih telah menjelaskan
Louis Maddox

1

jika instalasi Anda mendukung pcregrep, opsi multiline (-M) sangat berguna.

pcregrep -M -o '\AStarting activity for ID (\d+)\n(?!ID \1)' t.z

Mulai aktivitas untuk ID 33367

Dengan menggunakan situs kami, Anda mengakui telah membaca dan memahami Kebijakan Cookie dan Kebijakan Privasi kami.
Licensed under cc by-sa 3.0 with attribution required.