Sto analizzando un file della casella di posta che memorizza i rapporti del server di posta per i messaggi di posta recapitati non correttamente. Desidero estrarre indirizzi di posta errati, quindi che li rimuovo dal sistema. Il file di log ha questo aspetto:
...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.
Lindirizzo e-mail è 2 righe dopo una riga con “Il sistema di posta” Lutilizzo di grep in questo modo mi dà la riga “Il sistema di posta” e le due righe successive:
grep -A 2 "The mail system" mbox_file
Tuttavia, non so come rimuovere il Riga “Il sistema di posta” e la seconda riga vuota da questo output. Immagino di poter scrivere script PHP / Perl / Python per farlo, ma mi chiedo se questo sia possibile con grep o qualche altro strumento standard. Ho provato a dare un offset negativo al parametro -B:
grep -A 2 -B -2 "The mail system" mbox_file
Ma grep si lamenta:
grep: -2: invalid context length argument
Esiste un modo per farlo con grep?
Commenti
- -B accetta il numero come farebbe -A e visualizzerebbe il righe precedenti prima della partita.
- Sì, è vero, ma Milan ‘ non è interessato a ciò che precede la partita .. . Il problema che ha riscontrato è che -A e -B accettano solo valori positivi … e che in ogni caso -A e -B possono ‘ essere usati luno rispetto allaltro , come ha tentato di fare.
- Hum, giusto per essere sicuro: quelli sono indirizzi fittizi che non hai estratto (direttamente) dal file che ti è stato dato, giusto?
- @ Matthieu M. no, provengono da un file di registro reale. Ho pensato che, dal momento che sono comunque indirizzi non validi, a che cosa ‘ è necessario inventare indirizzi fittizi che potrebbero essere validi.
- stackoverflow.com/questions/8101701/…
Risposta
Il modo più semplice per risolverlo utilizzando solo grep
è reindirizzare un altro grep
invertito alla fine . Ad esempio:
grep -A 4 "The mail system" temp.txt | grep -v "The mail system" | grep -v "^\d*$"
Rispondi
Se non sei “t bloccato in utilizzando grep
, prova sed
…
sed -n "/The mail system/{n;n;p}"
Quando trova una riga contenente “Il sistema di posta”, legge due volte la riga successiva, tramite n;n;
, scartando ogni riga precedente mentre lo fa.
Rimane la terza riga del gruppo nello spazio pattern, che viene quindi stampato tramite il comando sed “s p
.. Lopzione -n
iniziale impedisce tutte le altre stampe .
Per stampare anche le due righe successive, è solo un caso di next e stampa n;p
altre due volte.
sed -n "/The mail system/{n; n;p; n;p; n;p}"
Le letture della riga successiva per le righe richieste possono essere accumulate e stampate in un unico blocco con un solo p
… N
legge la riga successiva e la aggiunge allo spazio del pattern,
Ecco la versione condensata finale …
sed -n "/The mail system/{n;n;N;N;p}"
Se vuoi un separatore di gruppi , simile a quello che grep potrebbe restituire, puoi usare il comando insert di sed ” i
(che deve essere lultimo comando su una riga) …
Ecco la sintassi per includere un separatore di gruppi
sed -n "/The mail system/{n;n;N;N;p;i-- }" > output-file # or | ...
Ecco loutput per la prima corrispondenza:
<[email protected]>: host mx1.hotmail.com[65.54.188.94] said: 550 Requested action not taken: mailbox unavailable (in reply to RCPT TO command) --
Commenti
- +1. Grazie. Non ‘ in questo caso, ma ‘ terrò questo segnalibro nel caso avessi cose più complicate da gestire.
- Questa è unottima risposta!
Risposta
grep -A 2 -B -2 "The mail system" mbox_file
-B
è per le righe precedenti, quindi non è necessario fornire il valore -negative.
grep -A 2 -B 2 "The mail system" mbox_file # This will work please check
Commenti
- Questo non risponde alla domanda.
-A 2 -B 2
stampa da due righe prima del contesto a 2 righe dopo il contesto. La domanda riguarda la stampa da 2 righe dopo il contesto a 4 righe dopo il contesto.
Risposta
I non ha senso usare solo grep, tranne se “è un vincolo rigoroso. Non può essere fatto con una sola chiamata a grep.
grep -A 2 "The mail system" mbox_file | tail -n +3
- grep: trova la riga e genera 2 righe dopo,
- tail: taglia le prime 2 righe (cioè inizia dalla terza riga).
Commenti
- Funziona solo se è presente una singola riga corrispondente, che probabilmente non è ciò che la domanda sta chiedendo.
- Questo non è ciò che la domanda ha chiesto ma mi aiuta nella mia situazione attuale :-).
- @ daniel.neumann Lo so, ma ero esattamente nei tuoi panni e pensavo che gli altri ‘ Google-fu lo faranno condurre anche qui.
Risposta
Se desideri rimuovere le prime 2 righe, collegale a sed
sed "1,2d"
come
grep -A 2 "The mail system" mbox_file | sed "1,2d"
Commenti
- Ti sei perso il fatto che lo schema ricorre molte volte. Se “Il sistema di posta” appare sulle righe 4, 14, 24, 34, …, lOP vuole vedere le righe 6, 16, 26, 36, … La tua risposta darà 6, 14-16, 24-26, 34- 36,….
Risposta
Questo stampa la 1 riga successiva che segue la corrispondenza regexp, usando Perl
perl -ne "print if( (/The mail system/ && ($end=1))..!$end-- )"