Jeg analyserer en postkassefil, der gemmer e-mail-serverrapporter for mislykket leveret e-mail. Jeg ønsker at udtrække dårlige e-mail-adresser, så at jeg fjerner dem fra systemet. Logfilen ser sådan ud:

...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-mail-adresse kommer 2 linjer efter en linje med “The mail system” Brug af grep som denne giver mig linjen “The mail system” og de næste to linjer:

grep -A 2 "The mail system" mbox_file 

Jeg ved dog ikke, hvordan jeg fjerner Linjen “Mailsystemet” og den anden tomme linje fra denne output. Jeg tror jeg kunne skrive PHP / Perl / Python-script for at gøre det, men jeg spekulerer på, om dette er muligt med grep eller et andet standardværktøj. Jeg forsøgte at give negativ forskydning til -B parameter:

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

Men grep klager:

grep: -2: invalid context length argument 

Er der en måde at gøre dette på med grep?

Kommentarer

  • -B accepterer tal som -A ville, og det ville vise forrige linjer før kampen.
  • Ja, det er sandt, men Milan er ikke ' t interesseret i, hvad der går forud for kampen .. Problemet han stødte på er, at -A og -B kun accepterer positive værdier … og at -A og -B under alle omstændigheder kan ' t bruges i forhold til hinanden , som han har forsøgt at gøre.
  • Hum, bare for at sikre dig: det er dummy-adresser, som du ikke (direkte) ekstraherede fra den fil, du fik, ikke?
  • @Matthieu M. nej, de er fra ægte logfil. Jeg regnede med, da de alligevel er ugyldige adresser, hvad ' er pointen med at opfinde dummy-adresser, der muligvis er gyldige.
  • stackoverflow.com/questions/8101701/…

Svar

Den enkleste måde at løse det kun på ved hjælp af grep er at pibe en mere inverteret grep i slutningen . 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 ved hjælp af grep, prøv sed

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

Når den finder en linje, der indeholder “Mailsystemet”, den læser den næste linje to gange via n;n; og kaster hver forrige linje, når den gør det.
Dette forlader 3. linje i din gruppe i mønsterområdet, som derefter udskrives via sed “s p kommando .. Den førende -n -indstilling forhindrer al anden udskrivning .

For at udskrive også de næste to linjer er det bare et tilfælde af næste og udskriv n;p to gange mere.

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

Den næste linje, der læses for de linjer, du har brug for, kan akkumuleres og udskrives en enkelt blok med kun en pN læser den næste linje og føjer den til mønsterområdet,

Her er den endelige kondenserede version …

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

Hvis du vil have en gruppeseparator svarende til hvad grep vil udgive, kan du bruge kommandoen sed “s indsæt i (som skal være den sidste kommando på en linje) …

Her er syntaksen for at inkludere en gruppeseparator

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

Her er output til første match:

<[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. Tak. Jeg har ikke ' jeg har ikke brug for det i dette tilfælde, men jeg ' ll holde dette bogmærke, hvis jeg får mere komplicerede ting at håndtere.
  • Dette er et godt svar!

Svar

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

-B er for tidligere linjer, så der er ikke behov for at give -negativ værdi.

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

Kommentarer

  • Dette svarer ikke på spørgsmålet. -A 2 -B 2 udskriver fra to linjer før konteksten til 2 linjer efter konteksten. Spørgsmålet handler om at udskrive fra 2 linjer efter konteksten til 4 linjer efter konteksten.

Svar

I ser ingen mening i kun at bruge grep (er), undtagen hvis “en streng begrænsning. Det kan ikke gøres med et opkald til grep.

grep -A 2 "The mail system" mbox_file | tail -n +3 
  • grep: Find linjen og output 2 linjer efter,
  • hale: klip de første 2 linjer (dvs. start fra den tredje linje).

Kommentarer

  • Dette fungerer kun, hvis der er en enkelt matchende linje, hvilket sandsynligvis ikke er, hvad spørgsmålet stilles.
  • Det er ikke det, spørgsmålet stillede, men det hjælper mig i min nuværende situation :-).
  • @ daniel.neumann Jeg ved det, men jeg var nøjagtigt i dine sko og troede andre ' Google-fu vil før også her.

Svar

Hvis du vil fjerne de første 2 linjer, rør den til sed

sed "1,2d" 

som i

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

Kommentarer

  • Du har gået glip af, at mønsteret forekommer mange gange. Hvis “Mailsystemet” vises på linie 4, 14, 24, 34,…, vil OPen se linier 6, 16, 26, 36, … Dit svar giver 6, 14-16, 24-26, 34- 36,….

Svar

Dette udskriver den næste 1 linje efter regexp-match ved hjælp af Perl

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

Skriv et svar

Din e-mailadresse vil ikke blive publiceret. Krævede felter er markeret med *