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 pN 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-- )" 

Legg igjen en kommentar

Din e-postadresse vil ikke bli publisert. Obligatoriske felt er merket med *