Bir satırı yalnızca sonraki satır belirli bir eşleşme İÇERMİYORSA yazdırın


12

Tamamlanmayan günlük etkinlikleri için bir günlük dosyası aramaya çalışıyorum. Örneğin, bir "ID 1234 için başlangıç ​​etkinliği ..." günlüğünü tutuyorum ve başarılı olursa sonraki satır "Etkinlik 1234 Tamamlandı" olacaktır.

Ben karşılık gelen "Tamamlandı" satırları tarafından takip DEĞİL "Başlıyor ..." satırları almaya çalışıyorum.

Örnek Günlük Dosyası

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

Bu örnekte, çıktı için:

Starting activity for ID 33367

... çünkü bunu "tamamlanmış" bir çizgi izlemiyor.

Bunu grepve ile yapmayı denedim awkama çok başarılı olamadım. Bu araçlardan biriyle yapılabileceğini düşünüyorum, ancak benim grepve awkpirzola gelişmiş değil.

Burada ihtiyacım olan sonuçları vermek için hızlı ve güvenilir grepveya awkkalıp arıyorum .


Grep + awk ile kolay olduğunu düşünmüyorum, ama bunu neden yaptığınızı biraz açıklayabilir misiniz? Tüm çalışan faaliyetlerin bir çıktısı, örneğin başarı ya da sonuçlanmadı mı?
daisy

@ warl0ck, ben "bitmemiş" arıyorum.
PattMauler

Yanıtlar:


10

İşte bir awkalternatif:

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

Çıktı:

Starting activity for ID 33367

Iİlişkili dizi kimlikleri görülmüştür ne izler.


Bu, "Başlatılıyor ..." ve "Tamamlandı ..." günlük satırlarının bitişik / sıralı olmadığı durumlara uyum sağladığı görülüyor. Teşekkürler @Thor!
PattMauler

Rica ederim. Bu sadece (neredeyse) rasgele boyut girişi ile verimli bir şekilde çalışmalıdır, çünkü sadece ID'yi saklar ve arama süresi O (1) 'dir.
Thor

Güzel. Sadece bir şey: @RobertL'den öğrendiğim gibi ( unix.stackexchange.com/a/243550/135943 ) bir dizi öğesi oluşturmak için bir değer atamanıza gerek yoktur. Yani bunun yerine I[$5] = 1kullanabilirsiniz I[$5]. (Değeri umursamazsınız, sadece öğenin var olmasını istiyorsanız ve bunu isimlendirmek bunu başarır.)
Wildcard

@Wildcard: Haklısınız, ancak OP'nin sorusunu ve peşinde olduğu grep benzeri çıktıyı inceledikten sonra, tüm satırı hatırlamak ve sonunda çıktı almak daha uygundur.
Thor

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

Bu işlem, tamamlanan dizeyle eşleşen bir satır izlemeyen tüm giriş satırlarını çıktıdan siler .


2

GNU sed ile bunu nasıl yapabileceğiniz aşağıda açıklanmıştır:

sed -r 'N; /([0-9]+)\n\w+\s+\1/d; P; D' infile
  • N desen alanına bir satır daha okur.
  • Eşleşme normal ifadesi, aynı kimliklerin bulunup bulunmadığını, kalıp alanı silinirse ( d) ve döngü yeniden başlatılırsa denetler .
  • Eşleşmediyse, desen alanındaki ( P) ilk satırı yazdırın ve silin ( D).

Burada uzatılmış bir şey göremiyorum ... bu yüzden -rgerekli değil, değil mi?
Louis Maddox

1
@lmmx: Gerekir, çünkü aksi takdirde yakalama grubunun kaçması gerekir ve aynı şey +nicelleştirici için de geçerlidir.
Thor

Ah tamam! Ben değiştirdim ve gerekli olmadığını söyledim, açıklamak için teşekkürler
Louis Maddox

1

kurulumunuz pcregrep'i destekliyorsa, çok satırlı (-M) seçeneği kullanışlı olur.

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

ID 33367 için başlangıç ​​etkinliği

Sitemizi kullandığınızda şunları okuyup anladığınızı kabul etmiş olursunuz: Çerez Politikası ve Gizlilik Politikası.
Licensed under cc by-sa 3.0 with attribution required.