Analyzuji soubor poštovní schránky, který ukládá zprávy e-mailového serveru pro neúspěšně doručený e-mail. Chci extrahovat špatné e-mailové adresy, takže že je odstraním ze systému. Soubor protokolu vypadá takto:

...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. 

E-mailová adresa je uvedena za 2 řádky za řádkem s „Poštovní systém“ . Takové použití grepu mi dává řádek „The mail system“ a další dva řádky:

grep -A 2 "The mail system" mbox_file 

Nevím však, jak odstranit Řádek „Poštovní systém“ a druhý prázdný řádek z tohoto výstupu. Myslím, že bych k tomu mohl napsat skript PHP / Perl / Python, ale zajímalo by mě, jestli je to možné pomocí grepu nebo jiného standardního nástroje. Snažil jsem se dát negativní offset parametru -B:

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

Ale grep si stěžuje:

grep: -2: invalid context length argument 

Existuje způsob, jak to provést pomocí grep?

Komentáře

  • -B přijímá číslici jako -A a zobrazí by předchozí řádky před zápasem.
  • Ano, to je pravda, ale Milan se ' nezajímá, co předchází zápasu .. . Problém, s nímž se setkal, je, že -A a -B přijímají pouze kladné hodnoty … a že v každém případě -A a -B nelze ' vzájemně použít , jak se o to pokusil.
  • Hum, jen pro jistotu: jedná se o fiktivní adresy, které jste (přímo) nezískali ze souboru, který jste dostali, že?
  • @ Matthieu M. ne, jsou ze skutečného souboru protokolu. Myslel jsem, že stejně jsou to neplatné adresy, jaký ' má smysl vymýšlet fiktivní adresy, které by mohly být platné.
  • stackoverflow.com/questions/8101701/…

odpověď

Nejjednodušší způsob, jak to vyřešit pouze pomocí grep, je na konec přivést ještě jednu obrácenou grep . Například:

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

Odpovědět

Pokud nejste přihlášeni pomocí grep zkuste sed

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

Když najde řádek obsahující „Poštovní systém“, přečte další řádek dvakrát pomocí n;n;, přičemž zahodí každý předchozí řádek.
Tím se ponechá třetí řádek vaší skupiny v prostoru vzorů, který se poté vytiskne pomocí příkazu sed „s p .. Přední -n možnost zabrání veškerému dalšímu tisku .

Chcete-li vytisknout také další dva řádky, je to jen případ next a print n;p ještě dvakrát.

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

Čtení dalšího řádku pro požadované řádky lze hromadit a vytisknout jeden blok pouze s jedním pN načte další řádek a připojí jej do prostoru vzoru,

Zde je konečná zhuštěná verze …

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

Pokud chcete oddělovač skupin , podobný tomu, jaký by měl grep výstup, můžete použít příkaz sed „s insert i (což musí být poslední příkaz na řádku) …

Zde je syntaxe, která obsahuje oddělovač skupin

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

Zde je výstup pro první shodu:

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

Komentáře

  • +1. Děkuji. V tomto případě to ' nepotřebuji, ale ' Tuto záložku si ponechám pro případ, že bych zvládl složitější věci.
  • To je skvělá odpověď!

Odpověď

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

-B je pro předchozí řádky, takže není nutné uvádět -negativní hodnotu.

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

Komentáře

  • To na otázku neodpovídá. -A 2 -B 2 tiskne ze dvou řádků před kontextem na 2 řádky za kontextem. Otázkou je tisk ze 2 řádků za kontextem do 4 řádků za kontextem.

Odpověď

I nevidí smysl používat pouze grep (y), kromě případů, kdy je to přísné omezení. Nelze to provést pomocí jediného volání grep.

grep -A 2 "The mail system" mbox_file | tail -n +3 
  • grep: Najděte řádek a vypište 2 řádky za,
  • ocas: ořízněte první 2 řádky (tj. začněte od třetího řádku).

Komentáře

  • Funguje to pouze v případě, že existuje jeden odpovídající řádek, což pravděpodobně není to, na co se otázka ptá.
  • To není to, na co se otázka ptá, ale to pomáhá mi v mé současné situaci :-).
  • @ daniel.neumann vím, ale byl jsem přesně ve tvých botách a myslel jsem si, že ostatní ' Google-fu bude vést také sem.

Odpověď

Pokud chcete odstranit první 2 řádky, přejděte do sed

sed "1,2d" 

jako v

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

Komentáře

  • Chybělo vám, že se vzor vyskytuje mnohokrát. Pokud se na řádcích 4, 14, 24, 34,… objeví „Poštovní systém“, OP chce vidět řádky 6, 16, 26, 36, … Vaše odpověď bude 6, 14-16, 24-26, 34- 36,….

Odpověď

Tím se vytiskne další 1 řádek následující po shodě regexp pomocí Perlu

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

Napsat komentář

Vaše e-mailová adresa nebude zveřejněna. Vyžadované informace jsou označeny *