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 p
… N
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-- )"