Analizuję plik skrzynki pocztowej, w którym przechowywane są raporty serwera e-mail o nieudane dostarczenie wiadomości e-mail. Chcę wyodrębnić złe adresy e-mail, aby 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 pojawia się 2 wiersze po wierszu z „Systemem poczty”. Używanie grep w ten sposób daje mi wiersz „System poczty” i kolejne dwa wiersze:
grep -A 2 "The mail system" mbox_file
Nie wiem jednak, jak usunąć z tego wyniku wiersz „System poczty” i drugi pusty wiersz. Myślę, że mógłbym napisać skrypt PHP / Perl / Python, aby to zrobić, ale zastanawiam się, czy jest to możliwe przy pomocy grep lub innego standardowego narzędzia. Próbowałem podać ujemne przesunięcie parametru -B:
grep -A 2 -B -2 "The mail system" mbox_file
Ale grep narzeka:
grep: -2: invalid context length argument
Czy można to zrobić za pomocą grep?
Odpowiedzi:
Najprostszym sposobem rozwiązania tego za pomocą
grep
samego tylko jest potokowanie jeszcze jednego odwróconegogrep
na końcu. Na przykład:źródło
Jeśli nie masz dostępu do korzystania
grep
, spróbujsed
...Gdy znajdzie wiersz zawierający „System poczty”, odczytuje następny wiersz dwa razy, za pomocą
n;n;
, odrzucając każdą poprzednią linię, gdy to robi.Pozostawia to trzecią linię twojej grupy w przestrzeni wzorów, która jest następnie drukowana za pomocą
p
komendy sed . Opcja wiodąca-n
zapobiega wszelkiemu drukowaniu.Aby wydrukować również dwa kolejne wiersze, jest to tylko przypadek następnego i wydrukuj
n;p
dwa razy więcej.Odczyty następnego wiersza dla potrzebnych wierszy można zgromadzić i wydrukować pojedynczy blok za pomocą tylko jednego
p
...N
odczytuje następny wiersz i dołącza go do obszaru wzorów,Oto ostateczna wersja skrócona ...
Jeśli potrzebujesz separatora grupowego , podobnego do wyjścia grep wouuld, możesz użyć polecenia wstawiania sed
i
(które musi być ostatnim poleceniem w linii) ...Oto składnia uwzględniająca separator grupy
Oto wynik pierwszego dopasowania:
źródło
-B
jest dla poprzednich wierszy, więc nie trzeba podawać wartości ujemnej.źródło
-A 2 -B 2
drukuje z dwóch linii przed kontekstem do 2 linii po kontekście. Pytanie dotyczy drukowania od 2 linii po kontekście do 4 linii po kontekście.Nie widzę sensu w używaniu tylko grep (s), chyba że jest to ścisłe ograniczenie. Nie można tego zrobić jednym wezwaniem do grep.
źródło
Spowoduje to wydrukowanie następnego 1 wiersza po dopasowaniu wyrażenia regularnego przy użyciu Perla
źródło