Parsuję plik skrzynki pocztowej, który przechowuje raporty serwera poczty e-mail pod kątem nieudanej dostawy wiadomości e-mail. Chcę wyodrębnić złe adresy e-mail, więc że usunę je z systemu. Plik dziennika wygląda następująco:

...some content... The mail system <[email protected]>: 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 <[email protected]>: host viking.optimumpro.net[79.101.51.82] said: 550 Unknown user (in reply to RCPT TO command) ...some content... The mail system <[email protected]>: host mta5.am0.yahoodns.net[74.6.140.64] said: 554 delivery error: dd This user doesn"t have a yahoo.com account ([email protected]) [0] - mta1172.mail.sk1.yahoo.com (in reply to end of DATA command) ...etc. 

Adres e-mail występuje w dwóch wierszach po wierszu z wyrażeniem „System pocztowy” . Użycie grepa w ten sposób daje mi wiersz „System pocztowy” i następne dwa wiersze:

grep -A 2 "The mail system" mbox_file 

Jednak nie wiem, jak usunąć Wiersz „systemu pocztowego” i drugi pusty wiersz tego wyjścia. Myślę, że mógłbym napisać skrypt PHP / Perl / Python, aby to zrobić, ale zastanawiam się, czy jest to możliwe za pomocą grepa lub innego standardowego narzędzia. Próbowałem podać ujemne przesunięcie dla parametru -B:

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

Ale grep narzeka:

grep: -2: invalid context length argument 

Czy istnieje sposób na zrobienie tego za pomocą grepa?

Komentarze

  • -B akceptuje liczby w taki sam sposób, jak -A i wyświetli poprzednie wiersze przed meczem.
  • Tak, to prawda, ale Mediolan nie ' nie interesuje się tym, co poprzedza mecz. . Problem, który napotkał polega na tym, że -A i -B akceptują tylko wartości dodatnie … i że w każdym przypadku -A i -B mogą ' t być używane względem siebie , tak jak próbował.
  • Hum, tylko dla pewności: to są fikcyjne adresy, których nie wyodrębniłeś (bezpośrednio) z otrzymanego pliku, prawda?
  • @Matthieu M. nie, pochodzą z prawdziwego pliku dziennika. Pomyślałem, że skoro i tak są to nieprawidłowe adresy, co ' jest celem wymyślania fałszywych adresów, które mogą być prawidłowe.
  • stackoverflow.com/questions/8101701/…

Odpowiedź

Najprostszym sposobem rozwiązania tego problemu przy użyciu tylko grep jest wyprowadzenie na końcu jeszcze jednego odwróconego grep . Na przykład:

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

Answer

Jeśli nie jesteś zablokowany używając grep, spróbuj sed

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

Kiedy znajduje wiersz zawierający „The mail system”, dwukrotnie czyta następny wiersz, poprzez n;n;, pomijając przy tym każdą poprzednią linię.
To pozostawia trzeci wiersz Twojej grupy w przestrzeni wzorca, która jest następnie drukowana za pomocą polecenia sed „s p. Początkowa opcja -n zapobiega wszelkim innym drukom .

Aby wydrukować również następne dwa wiersze, wystarczy wpisać następny i wypisać n;p jeszcze dwa razy.

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

Odczyty w następnym wierszu żądanych wierszy można gromadzić i drukować jako pojedynczy blok z tylko jednym pN czyta następną linię i dołącza ją do przestrzeni wzorców,

Oto ostateczna, skondensowana wersja …

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

Jeśli potrzebujesz separatora grup , podobnego do tego, co wyprowadził grep, możesz użyć polecenia sed „s wstaw i (które musi być ostatnim poleceniem w wierszu) …

Oto składnia dołączania separatora grup

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

Oto dane wyjściowe dla pierwszego dopasowania:

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

Komentarze

  • +1. Dziękuję. Nie ' nie potrzebuję tego w tym przypadku, ale ' Zachowam tę zakładkę na wypadek, gdybym potrzebował bardziej skomplikowanych rzeczy.
  • To świetna odpowiedź!

Odpowiedź

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

-B dotyczy poprzednich wierszy, więc nie ma potrzeby podawania -negatywnej wartości.

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

Komentarze

  • To nie odpowiada na pytanie. -A 2 -B 2 drukuje od dwóch wierszy przed kontekstem do dwóch wierszy po kontekście. Pytanie dotyczy drukowania od 2 linii po kontekście do 4 linii po kontekście.

Odpowiedź

I nie widzę sensu w używaniu tylko grep (s), chyba że jest to „ścisłe ograniczenie. Nie można tego zrobić za pomocą jednego wywołania grepa”.

grep -A 2 "The mail system" mbox_file | tail -n +3 
  • grep: znajdź linię i wyprowadź 2 wiersze po,
  • tail: wytnij pierwsze 2 wiersze (tj. zacznij od trzeciego wiersza).

Komentarze

  • Działa to tylko wtedy, gdy istnieje jedna pasująca linia, co prawdopodobnie nie jest tym, o co chodzi w pytaniu.
  • To nie jest to, o co pytano, ale to pomaga mi w mojej obecnej sytuacji :-).
  • @ daniel.neumann Wiem, ale byłem dokładnie na twoim miejscu i myślałem, że inni ' Google-fu tu też prowadzić.

Odpowiedź

Jeśli chcesz usunąć pierwsze 2 wiersze, przeprowadź wyprowadzenie do sed

sed "1,2d" 

jak w

 grep -A 2 "The mail system" mbox_file | sed "1,2d"  

Komentarze

  • Przegapiłeś fakt, że wzorzec występuje wiele razy. Jeśli „System poczty” pojawia się w wierszach 4, 14, 24, 34,…, PO chce zobaczyć wiersze 6, 16, 26, 36,… Twoja odpowiedź da 6, 14-16, 24-26, 34- 36,….

Odpowiedź

Drukuje następną 1 linię po dopasowaniu wyrażenia regularnego, używając Perla

perl -ne "print if( (/The mail system/ && ($end=1))..!$end-- )" 

Dodaj komentarz

Twój adres email nie zostanie opublikowany. Pola, których wypełnienie jest wymagane, są oznaczone symbolem *