Her bir grep sonucundan sonra 2-4 satırları nasıl gösterilir?


40

Başarısız bir şekilde gönderilen e-posta için e-posta sunucusu raporlarını saklayan bir posta kutusu dosyasını ayrıştırıyorum. Kötü e-posta adreslerini çıkarmak istiyorum, böylece sistemden kaldırabilirim. Günlük dosyası şöyle görünür:

...some content...
                   The mail system

<slavicatomic118@hotmail.com>: host mx1.hotmail.com[65.54.188.94] said: 550
    Requested action not taken: mailbox unavailable (in reply to RCPT TO
    command)

...some content...
                   The mail system

<oki88@optimumpro.net>: host viking.optimumpro.net[79.101.51.82] said: 550
    Unknown user (in reply to RCPT TO command)

...some content...
                   The mail system

<sigirna_luka@yahoo.com>: host mta5.am0.yahoodns.net[74.6.140.64] said: 554
    delivery error: dd This user doesn't have a yahoo.com account
    (sigirna_luka@yahoo.com) [0] - mta1172.mail.sk1.yahoo.com (in reply to end
    of DATA command)

...etc.

E-posta adresi "Posta sistemi" olan bir satırdan 2 satır sonra gelir. Grep'i bu şekilde kullanmak bana "posta sistemi" satırı ve sonraki iki satırı verir:

grep -A 2 "The mail system" mbox_file

Ancak, "Posta sistemi" satırını ve ikinci boş satırın bu çıktıdan nasıl kaldırılacağını bilmiyorum. Bunu yapmak için PHP / Perl / Python betiği yazabilirim, ancak bunun grep veya başka bir standart araçla mümkün olup olmadığını merak ediyorum. -B parametresine negatif ofset vermeye çalıştım:

grep -A 2 -B -2 "The mail system" mbox_file

Ancak grep şikayetçi:

grep: -2: invalid context length argument

Bunu grep ile yapmanın bir yolu var mı?


3
-B, -A'nın olduğu gibi rakamları kabul eder ve maçtan önceki satırları gösterir.
Nikhil Mulley

3
Evet, bu doğru, ancak Milan maçtan önce gelenlerle ilgilenmiyor ... Karşılaştığı sorun, -A ve -B’nin sadece pozitif değerleri kabul etmesi ... ve her durumda, -A ve -B’nin Yapmaya çalıştığı gibi birbirine göre kullanılmamalıdır.
Peter.O

1
Hum, sadece emin olmak için: bunlar size verilen dosyadan (doğrudan) çıkartmadığınız aptal adreslerdir, değil mi?
Matthieu M.,

1
@ Matthieu M. hayır, onlar gerçek günlük dosyasından. Yine de geçersiz adresler oldukları için geçerli olabilecek sahte adresleri icat etmenin ne demek olduğunu düşündüm.
Milan Babuškov

Yanıtlar:


29

grepSadece onu kullanarak çözmenin en basit yolu grep, sonunda ters çevrilmiş bir tane daha borulamaktır . Örneğin:

grep -A 4 "The mail system" temp.txt | grep -v "The mail system" | grep -v '^\d*$'

28

Kullanmak için kilitlenmediyseniz grep, deneyin sed...

sed -n '/The mail system/{n;n;p}' 

"Posta sistemi" içeren bir satır bulduğunda, bir sonraki satırı iki kez okur ve n;n;önceki satırları olduğu gibi atar.
Bu, grubunuzun 3. satırını desen uzayında bırakır ve daha sonra sed pkomutuyla yazdırılır . Baştaki -nseçenek, diğer tüm baskıları önler.

Sonraki iki satırı da yazdırmak için, bir sonraki durumdur ve n;p iki kez daha yazdırın .

sed -n '/The mail system/{n; n;p; n;p; n;p}'   

İhtiyacınız olan hatlar için okunan bir sonraki satır toplanıp tek bir blokla basılabilir p... bir Nsonraki satırı okur ve kalıp alanına ekler,

İşte son yoğun versiyon ...

sed -n '/The mail system/{n;n;N;N;p}'   

Eğer grep çıktısına benzer bir grup ayırıcı istiyorsanız , sed'in insert komutunu kullanabilirsiniz i(bir satırdaki son komut olmalıdır) ...

İşte grup ayırıcıyı içeren sözdizimi

sed -n '/The mail system/{n;n;N;N;p;i--
       }' > output-file  # or | ...

İşte ilk eşleşmenin çıktısı:

<slavicatomic118@hotmail.com>: host mx1.hotmail.com[65.54.188.94] said: 550
    Requested action not taken: mailbox unavailable (in reply to RCPT TO
    command)                                                                    
--

+1. Teşekkürler. Bu durumda buna ihtiyacım yok, ancak daha karmaşık işleri halledebilmem için bu yer imini tutacağım.
Milan Babuškov

Bu harika bir cevap!
dotancohen

9
grep -A 2 -B -2 "The mail system" mbox_file

-B önceki satırlar içindir, bu nedenle -digatif bir değer vermenize gerek yoktur.

grep -A 2 -B 2 "The mail system" mbox_file   # This will work please check

Bu soruya cevap vermiyor. -A 2 -B 2bağlamdan önce iki satırdan bağlamdan sonra 2 satıra yazdırır. Soru bağlamdan sonra 2 satırdan bağlamdan sonra 4 satıra yazdırmakla ilgilidir.
daniel.neumann

1

Sıkı bir kısıtlama olmadığı sürece, sadece grep (ler) kullanmanın hiçbir anlamı göremiyorum. Grep'e bir çağrı ile yapılamaz.

grep -A 2 "The mail system" mbox_file | tail -n +3
  • grep: Satırı bulun ve sonra 2 satır çıktı alın.
  • kuyruk: ilk 2 çizgiyi kes (yani üçüncü çizgiden başla).

2
Bu sadece, tek bir eşleşme çizgisi varsa işe yarar, bu muhtemelen sorunun ne sorduğu değildir.
jw013

Sorunun sorduğu şey bu değil ama şu anki durumumda bana yardımcı oluyor :-).
daniel.neumann

1
@ daniel.neumann Biliyorum ama tam olarak ayakkabınızdaydım ve başkalarının Google-fu’sının da burada yol göstereceğini düşündüm.
TWiStErRob

0

Bu, Perge kullanarak regexp eşleşmesinin ardından bir sonraki 1 satırı yazdırır.

perl -ne 'print if( (/The mail system/ && ($end=1))..!$end-- )' 
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.