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