Je « suis en train danalyser un fichier de boîte aux lettres qui stocke les rapports du serveur de messagerie pour les courriers électroniques non remis. Je souhaite extraire les mauvaises adresses électroniques, donc que je les supprime du système. Le fichier journal ressemble à ceci:

...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. 

Ladresse e-mail vient 2 lignes après une ligne avec « Le système de messagerie » . Utiliser grep comme celui-ci me donne la ligne « Le système de messagerie » et les deux lignes suivantes:

grep -A 2 "The mail system" mbox_file 

Cependant, je ne sais pas comment supprimer le Ligne « Le système de messagerie » et la deuxième ligne vide de cette sortie. Je suppose que je pourrais écrire un script PHP / Perl / Python pour le faire, mais je me demande si cela est possible avec grep ou un autre outil standard. Jai essayé de donner un décalage négatif au paramètre -B:

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

Mais grep se plaint:

grep: -2: invalid context length argument 

Y a-t-il un moyen de faire cela avec grep?

Commentaires

  • -B accepte les nombres comme -A le ferait, et il afficherait le lignes précédentes avant le match.
  • Oui, cest vrai, mais Milan nest ‘ pas intéressé par ce qui précède le match. . Le problème qu’il a rencontré est que -A et -B n’acceptent que des valeurs positives … et que dans tous les cas, -A et -B peuvent ‘ être utilisés les uns par rapport aux autres , comme il a tenté de le faire.
  • Hum, juste pour être sûr: ce sont des adresses factices que vous navez pas (directement) extraites du fichier que vous avez reçu, nest-ce pas?
  • @Matthieu M. non, ils proviennent dun vrai fichier journal. Jai pensé que ce sont des adresses invalides de toute façon, quel ‘ est lintérêt dinventer des adresses factices qui pourraient être valides.
  • stackoverflow.com/questions/8101701/…

Réponse

Le moyen le plus simple de le résoudre en utilisant uniquement grep est de rediriger un autre grep inversé à la fin . Par exemple:

grep -A 4 "The mail system" temp.txt | grep -v "The mail system" | grep -v "^\d*$" 

Réponse

Si vous nêtes pas verrouillé en utilisant grep, essayez sed

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

Quand il trouve une ligne contenant « Le système de messagerie », il lit deux fois la ligne suivante, via le n;n;, en supprimant chaque ligne précédente comme il le fait.
Cela laisse la 3ème ligne de votre groupe dans lespace des motifs, qui est ensuite imprimé via la commande sed « s p .. Loption principale -n empêche toute autre impression .

Pour imprimer également les deux lignes suivantes, cest juste un cas de next et imprimer n;p deux fois de plus.

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

Les lectures de la ligne suivante pour les lignes dont vous avez besoin peuvent être accumulées et imprimées en un seul bloc avec un seul pN lit la ligne suivante et lajoute à lespace du motif,

Voici la version finale condensée …

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

Si vous voulez un séparateur de groupe , similaire à ce que grep produirait, vous pouvez utiliser la commande insert de sed  » i (qui doit être la dernière commande sur une ligne) …

Voici la syntaxe pour inclure un séparateur de groupe

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

Voici la sortie pour la première correspondance:

<[email protected]>: host mx1.hotmail.com[65.54.188.94] said: 550 Requested action not taken: mailbox unavailable (in reply to RCPT TO command) -- 

Commentaires

  • +1. Merci. Je nai ‘ pas besoin dans ce cas, mais je ‘ Je garderai ceci en signet au cas où jaurais des choses plus compliquées à gérer.
  • Cest une excellente réponse!

Réponse

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

-B est pour les lignes précédentes, donc pas besoin de donner une valeur négative.

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

Commentaires

  • Cela ne répond pas à la question. -A 2 -B 2 imprime de deux lignes avant le contexte à 2 lignes après le contexte. La question concerne limpression de 2 lignes après le contexte à 4 lignes après le contexte.

Réponse

I ne voit aucun intérêt à nutiliser que grep (s), sauf si cela « est une contrainte stricte. Cela ne peut pas être fait avec un seul appel à grep.

grep -A 2 "The mail system" mbox_file | tail -n +3 
  • grep: trouve la ligne et affiche 2 lignes après,
  • queue: coupe les 2 premières lignes (cest-à-dire commence à partir de la troisième ligne).

Commentaires

  • Cela ne fonctionne que sil y a une seule ligne correspondante, ce qui nest probablement pas ce que la question demande.
  • Ce nest rien de ce que la question a demandé mais cest maide dans ma situation actuelle :-).
  • @ daniel.neumann Je sais, mais jétais exactement à ta place et je pensais que les autres ‘ Google-fu le feront conduire ici aussi.

Réponse

Si vous souhaitez supprimer les 2 premières lignes, dirigez-les vers sed

sed "1,2d" 

comme dans

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

Commentaires

  • Vous avez manqué le fait que le modèle se produit plusieurs fois. Si «Le système de messagerie» apparaît aux lignes 4, 14, 24, 34,…, lOP veut voir les lignes 6, 16, 26, 36,… Votre réponse donnera 6, 14-16, 24-26, 34- 36,….

Réponse

Ceci imprime la ligne suivante suivant la correspondance de lexpression rationnelle, en utilisant Perl

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

Laisser un commentaire

Votre adresse e-mail ne sera pas publiée. Les champs obligatoires sont indiqués avec *