Ik “m ontleed een mailboxbestand dat e-mailserverrapporten opslaat voor niet succesvol afgeleverde e-mail. Ik wil slechte e-mailadressen extraheren, dus dat ik ze uit het systeem verwijder. Het logbestand ziet er als volgt uit:

...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-mailadres komt 2 regels na een regel met “Het mailsysteem” Als ik grep op deze manier gebruik, krijg ik de regel “The mail system” en de volgende twee regels:

grep -A 2 "The mail system" mbox_file 

Ik weet echter niet hoe ik de “The mail system” regel en de tweede lege regel van deze output. Ik denk dat ik hiervoor PHP / Perl / Python-script zou kunnen schrijven, maar ik vraag me af of dit mogelijk is met grep of een andere standaardtool. Ik heb geprobeerd een negatieve offset te geven aan de parameter -B:

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

Maar grep klaagt:

grep: -2: invalid context length argument 

Is er een manier om dit te doen met grep?

Reacties

  • -B accepteert cijfers zoals -A zou, en het zou de vorige regels vóór de wedstrijd.
  • Ja, dat is waar, maar Milaan is niet ‘ geïnteresseerd in wat er aan de wedstrijd voorafgaat .. . Het probleem dat hij tegenkwam is dat -A en -B alleen positieve waarden accepteren … en dat -A en -B in elk geval ‘ niet relatief ten opzichte van elkaar kunnen worden gebruikt , zoals hij heeft geprobeerd te doen.
  • Hum, om er zeker van te zijn: dat zijn nepadressen die je niet (direct) uit het bestand hebt gehaald, toch?
  • @Matthieu M. nee, ze komen uit een echt logbestand. Omdat het sowieso ongeldige adressen zijn, dacht ik dat ‘ het nut is van het verzinnen van dummy-adressen die geldig zouden kunnen zijn.
  • stackoverflow.com/questions/8101701/…

Antwoord

De eenvoudigste manier om het op te lossen door alleen grep te gebruiken, is door nog een omgekeerde grep aan het einde . Bijvoorbeeld:

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

Answer

Als u niet bent vergrendeld aan gebruik grep, probeer sed

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

Wanneer het vindt een regel met “The mail system”, het leest de volgende regel twee keer, via de n;n;, waarbij elke vorige regel wordt weggegooid zoals het doet.
Hierdoor blijft de derde regel over van uw groep in de patroonruimte, die vervolgens wordt afgedrukt via de opdracht sed “s p .. De eerste optie -n voorkomt alle andere .

Om ook de volgende twee regels af te drukken, is het slechts een geval van next en print n;p nog twee keer.

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

De volgende regel leest voor de regels die u nodig heeft, kan worden verzameld en afgedrukt als een enkel blok met slechts één pN leest de volgende regel en voegt deze toe aan de patroonruimte,

Hier is de laatste verkorte versie …

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

Als je een group seperator wilt, vergelijkbaar met wat grep zou uitvoeren, kun je het insert commando van sed “s gebruiken i (dit moet het laatste commando op een regel zijn) …

Hier is de syntaxis om een groepscheidingsteken

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

Hier is de uitvoer voor de eerste overeenkomst:

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

Reacties

  • +1. Bedankt. Ik heb ‘ het in dit geval niet nodig, maar ik ‘ Ik zal dit als bladwijzer bewaren voor het geval ik ingewikkelder dingen te verwerken krijg.
  • Dit is een geweldig antwoord!

Antwoord

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

-B is voor vorige regels, dus het is niet nodig om -negatieve waarde op te geven.

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

Reacties

  • Dit geeft geen antwoord op de vraag. -A 2 -B 2 drukt af van twee regels vóór de context tot twee regels na de context. De vraag gaat over het afdrukken van 2 regels na de context tot 4 regels na de context.

Answer

I het heeft geen zin om alleen grep (s) te gebruiken, behalve als dat “een strikte beperking is. Het kan niet worden gedaan met één aanroep van grep.

grep -A 2 "The mail system" mbox_file | tail -n +3 
  • grep: zoek de regel en voer 2 regels daarna uit,
  • tail: knip de eerste 2 regels (dwz begin vanaf de derde regel).

Opmerkingen

  • Dit werkt alleen als er één overeenkomende regel is, wat waarschijnlijk niet is wat de vraag stelt.
  • Dat is niets waar de vraag om vroeg, maar het helpt me in mijn huidige situatie :-).
  • @ daniel.neumann Ik weet het, maar ik stond precies in jouw schoenen en dacht dat anderen ‘ Google-fu zullen leid hier ook.

Antwoord

Als u de eerste 2 regels wilt verwijderen, leid deze dan door naar sed

sed "1,2d" 

zoals in

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

Reacties

  • Je hebt gemist dat het patroon vaak voorkomt. Als “The mail system” verschijnt op regel 4, 14, 24, 34, …, wil het OP regel 6, 16, 26, 36, … zien. Je antwoord zal 6, 14-16, 24-26, 34- zijn. 36,….

Answer

Hiermee wordt de volgende regel afgedrukt na de regexp-overeenkomst, met behulp van Perl

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

Geef een reactie

Het e-mailadres wordt niet gepubliceerd. Vereiste velden zijn gemarkeerd met *