Analizez un fișier de cutie poștală care stochează rapoartele serverului de e-mail pentru e-mailurile livrate fără succes. Doresc să extrag adrese de e-mail greșite, că le elimin din sistem. Fișierul jurnal arată astfel:

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

Adresa de e-mail vine 2 linii după o linie cu „Sistemul de poștă electronică” . Folosind grep așa îmi dă linia „Sistemul de poștă electronică” și următoarele două linii:

grep -A 2 "The mail system" mbox_file 

Cu toate acestea, nu știu cum să elimin Linia „Sistemul de poștă electronică” și a doua linie goală din această ieșire. Cred că aș putea scrie script PHP / Perl / Python pentru ao face, dar mă întreb dacă acest lucru este posibil cu grep sau cu un alt instrument standard. Am încercat să dau un offset negativ parametrului -B:

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

Dar grep se plânge:

grep: -2: invalid context length argument 

Există o modalitate de a face acest lucru cu grep?

Comentarii

  • -B acceptă cifra așa cum ar fi -A și ar afișa liniile anterioare înainte de meci.
  • Da, este adevărat, dar Milano nu este ‘ interesat de ceea ce precede meciul .. . Problema pe care a întâmpinat-o este că -A și -B acceptă doar valori pozitive … și că, în orice caz, -A și -B nu pot ‘ să poată fi utilizate una față de cealaltă , așa cum a încercat să facă.
  • Hum, doar pentru a vă asigura că acestea sunt adrese false care nu le-ați extras (direct) din fișierul care vi s-a dat, nu?
  • @Matthieu M. nu, sunt dintr-un fișier jurnal real. M-am gândit, întrucât oricum sunt adrese nevalide, care este ‘ care este punctul de a inventa adrese false care ar putea fi valabile.
  • stackoverflow.com/questions/8101701/…

Răspuns

Cel mai simplu mod de a-l rezolva folosind numai grep, este să introduceți încă un canal grep inversat la sfârșit . De exemplu:

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

Răspunde

Dacă nu ești blocat în folosind grep, încercați sed

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

Când găsește o linie care conține „Sistemul de poștă electronică”, citește următoarea linie de două ori, prin n;n;, aruncând fiecare linie anterioară în timp ce o face.
Aceasta rămâne a treia linie grupului dvs. în spațiul modelului, care este apoi tipărit prin comanda sed „s p .. Opțiunea principală -n împiedică toate celelalte tipăriri .

Pentru a imprima și următoarele două rânduri, este doar un caz de next și print n;p încă de două ori.

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

Citirea următoarei linii pentru liniile de care aveți nevoie poate fi acumulată și tipărită într-un singur bloc cu un singur pN citește următoarea linie și o adaugă la spațiul modelului,

Iată versiunea finală condensată …

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

Dacă doriți un separator de grup , similar cu rezultatul grep, puteți utiliza comanda sed „s insert i (care trebuie să fie ultima comandă pe o linie) …

Iată sintaxa pentru a include un separator de grup

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

Iată rezultatul pentru prima potrivire:

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

Comentarii

  • +1. Mulțumesc. Nu ‘ nu am nevoie în acest caz, dar ‘ Voi păstra acest marcaj în caz că voi primi lucruri mai complicate.
  • Acesta este un răspuns minunat!

Răspuns

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

-B este pentru liniile anterioare, deci nu este nevoie să dați valoare -negativă.

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

Comentarii

  • Aceasta nu răspunde la întrebare. -A 2 -B 2 tipărește de la două linii înainte de context la 2 linii după context. Întrebarea este despre tipărirea de la 2 linii după context la 4 linii după context.

Răspuns

I nu văd niciun rost să folosiți numai grep (s), cu excepția cazului în care „este o constrângere strictă. Nu se poate face cu un singur apel către grep.

grep -A 2 "The mail system" mbox_file | tail -n +3 
  • grep: Găsiți linia și scoateți 2 linii după,
  • coadă: tăiați primele 2 linii (adică începeți de la a treia linie).

Comentarii

  • Acest lucru funcționează numai dacă există o singură linie potrivită, care probabil nu este ceea ce pune întrebarea.
  • Nu este nimic din ceea ce a cerut întrebarea, ci mă ajută în situația mea actuală :-).
  • @ daniel.neumann știu, dar eram exact în locul tău și am crezut că alții ‘ Google-fu vor conduce și aici.

Răspuns

Dacă doriți să eliminați primele 2 linii, trimiteți-l la sed

sed "1,2d" 

ca în

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

Comentarii

  • Ați ratat faptul că tiparul apare de multe ori. Dacă „Sistemul de poștă electronică” apare pe liniile 4, 14, 24, 34, …, PO dorește să vadă liniile 6, 16, 26, 36, … Răspunsul dvs. va da 6, 14-16, 24-26, 34- 36,….

Răspuns

Aceasta tipărește următoarea 1 linie după potrivirea regexp, folosind Perl

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

Lasă un răspuns

Adresa ta de email nu va fi publicată. Câmpurile obligatorii sunt marcate cu *