Jeg analyserer en postboksfil som lagrer e-postserverrapporter for mislykket levert e-post. Jeg ønsker å trekke ut dårlige e-postadresser, så at jeg fjerner dem fra systemet. Loggfilen ser slik ut:
...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-postadressen kommer to linjer etter en linje med «The mail system» Å bruke grep som dette gir meg «The mail system» -linjen og de neste to linjene:
grep -A 2 "The mail system" mbox_file
Jeg vet imidlertid ikke hvordan jeg skal fjerne «Mailsystemet» -linjen og den andre tomme linjen fra denne utgangen. Jeg antar at jeg kunne skrive PHP / Perl / Python-skript for å gjøre det, men jeg lurer på om dette er mulig med grep eller et annet standardverktøy. Jeg prøvde å gi negativ forskyvning til -B parameter:
grep -A 2 -B -2 "The mail system" mbox_file
Men grep klager:
grep: -2: invalid context length argument
Er det en måte å gjøre dette med grep?
Kommentarer
- -B godtar tall som -A ville, og det vil vise forrige linjer før kampen.
- Ja, det stemmer, men Milan er ikke ' t interessert i hva som går foran kampen .. Problemet han opplevde er at -A og -B bare aksepterer positive verdier … og at -A og -B uansett kan ' t brukes i forhold til hverandre , som han har forsøkt å gjøre.
- Hum, bare for å være sikker på: det er dummy-adresser som du ikke (direkte) hentet fra filen du fikk, ikke sant?
- @Matthieu M. nei, de er fra ekte loggfil. Jeg skjønte at de uansett er ugyldige adresser, hva ' er poenget med å finne opp dummy-adresser som kan være gyldige.
- stackoverflow.com/questions/8101701/…
Svar
Den enkleste måten å løse det bare ved å bruke grep
, er å pipe en ytterligere invertert grep
på slutten . For eksempel:
grep -A 4 "The mail system" temp.txt | grep -v "The mail system" | grep -v "^\d*$"
Svar
Hvis du ikke er låst til bruk grep
, prøv sed
…
sed -n "/The mail system/{n;n;p}"
Når den finner en linje som inneholder «E-postsystemet», den leser neste linje to ganger, via n;n;
, og kaster hver forrige linje når den gjør det.
Dette forlater 3. linje av gruppen din i mønsterområdet, som deretter skrives ut via sed «s p
-kommandoen. Det ledende alternativet -n
forhindrer all annen utskrift .
For å skrive ut de to neste linjene også, er det bare et tilfelle av neste og skriv ut n;p
to ganger til.
sed -n "/The mail system/{n; n;p; n;p; n;p}"
Neste linje som leses for linjene du trenger, kan akkumuleres og skrives ut en enkelt blokk med bare en p
… N
leser neste linje og legger den til mønsterområdet,
Her er den endelige, kondenserte versjonen …
sed -n "/The mail system/{n;n;N;N;p}"
Hvis du vil ha en gruppeseparator , i likhet med hva grep vil sende ut, kan du bruke kommandoen sed «s insert i
(som må være den siste kommandoen på en linje) …
Her er syntaksen for å inkludere en gruppeseparator
sed -n "/The mail system/{n;n;N;N;p;i-- }" > output-file # or | ...
Her er utgangen for første kamp:
<[email protected]>: host mx1.hotmail.com[65.54.188.94] said: 550 Requested action not taken: mailbox unavailable (in reply to RCPT TO command) --
Kommentarer
- +1. Takk. Jeg trenger ikke ' t trenger det i dette tilfellet, men jeg ' vil holde dette bokmerket hvis jeg får mer kompliserte ting å håndtere.
- Dette er et flott svar!
Svar
grep -A 2 -B -2 "The mail system" mbox_file
-B
er for tidligere linjer, så det er ikke nødvendig å gi -negativ verdi.
grep -A 2 -B 2 "The mail system" mbox_file # This will work please check
Kommentarer
- Dette svarer ikke på spørsmålet.
-A 2 -B 2
skriver ut fra to linjer før konteksten til to linjer etter konteksten. Spørsmålet handler om å skrive ut fra 2 linjer etter konteksten til 4 linjer etter konteksten.
Svar
I ser ikke noe poeng i å bare bruke grep (er), bortsett fra hvis «en streng begrensning. Det kan ikke gjøres med ett kall til grep.
grep -A 2 "The mail system" mbox_file | tail -n +3
- grep: Finn linjen og skriv ut 2 linjer etter,
- hale: kutt de første 2 linjene (dvs. start fra tredje linje).
Kommentarer
- Dette fungerer bare hvis det er en enkelt samsvarende linje, som sannsynligvis ikke er det spørsmålet stiller.
- Det er ingenting det spørsmålet ba om, men det hjelper meg i min nåværende situasjon :-).
- @ daniel.neumann vet jeg, men jeg var akkurat i skoene dine og trodde andre ' Google-fu vil føre her også.
Svar
Hvis du vil fjerne de to første linjene, rør den til sed
sed "1,2d"
som i
grep -A 2 "The mail system" mbox_file | sed "1,2d"
Kommentarer
- Du har savnet det faktum at mønsteret forekommer mange ganger. Hvis “Mailsystemet” vises på linje 4, 14, 24, 34,…, vil OP se linjene 6, 16, 26, 36, … Svaret ditt vil gi 6, 14-16, 24-26, 34- 36,….
Svar
Dette skriver ut neste 1 linje etter regexp-samsvar, ved hjelp av Perl
perl -ne "print if( (/The mail system/ && ($end=1))..!$end-- )"