un ptit peu d'aide en Bash - Codes et scripts - Linux et OS Alternatifs
Marsh Posté le 19-05-2006 à 18:25:39
ReplyMarsh Posté le 19-05-2006 à 18:29:57
dchost99 a écrit : une soluc un peu differente |
quel rapport ? sachant que je ne connais justement pas les destinataire mais que je veux les lister
Marsh Posté le 19-05-2006 à 18:47:52
peut-être commencer avec un
grep "@" ton_fichier
ça permet déjà de filtrer les lignes qui contiennent une adresse
Marsh Posté le 20-05-2006 à 14:05:12
ReplyMarsh Posté le 20-05-2006 à 14:36:38
macfennec a écrit : le poste de Mjules répond à ta question non ? Sinon, sois plus explicite stp. |
Nan ça répond pas.
je ne veux récuperer QUE le texte qui correspond au champ "To:"
un exemple :
---------------------------------------------
Return-Path: <user1@domain.com>
X-Original-To: moi@domain.com
Delivered-To: moi@domain.com
Received: from mail.labas.com (mail.labas.com [276.67.09.32])
by smtp.moi.com (Postfix) with ESMTP id DdfsdfED
for <moi@domain.com>; Fri, 14 Apr 2006 16:47:44 +0200 (CEST)
To: moi@domain.com, toto@domain2.com,
toto2@domain3.com, fgdfg@domain4.com,
tructruc@domain5.com, luilui@domain5.com
Subject: truc
MIME-Version: 1.0
X-Mailer: Lotus Notes Release 6.5 September 26, 2003
Message-ID: <OFDB68A113.sdfdsfdsfdsfdsfsd-80257150.0056F0EE@dfsdfsd>
From: user1@domain.com
Date: Fri, 14 Apr 2006 14:52:27 +0100
Return-Receipt-To: user1@domain.com
X-MIMETrack: Serialize by Router on dsfsdf(Release 6.5.1|January 21, 2004) at 14/04/2006
15:52:32,
Serialize complete at 14/04/2006 15:52:32
Content-Type: multipart/alternative; boundary="=_alternative00567402340257150_="
----------------------------------------------------
et je voudrais récuperer uniquement ça :
To: moi@domain.com, toto@domain2.com, toto2@domain3.com, fgdfg@domain4.com, tructruc@domain5.com, luilui@domain5.com
Marsh Posté le 20-05-2006 à 21:38:08
Bon je m'ennuyais alors voilà :
Expression régulière inside http://expreg.com/ needed :
Pour arriver au résultat final, je pense qu'il sera plus facile de cumuler plusieurs grep en renvoyant la sortie de l'un sur l'entrée de l'autre avec des pipe ( | )
Pour extraire les adresses email déjà (à l'arrache) :
cat mail.txt | grep -e '\w*@\w*.\w*' -o
pour extraire juste le To, c'est plus dur, je pensais que ça irait tout seul mais ".*" (censé représenter une suite de n'importe quels caractères de 0,1 ou plusieurs caractères) se vautre sur le passage de ligne :
cat mail.txt | grep -e 'To:.*' -o
> ça ne prend qu'une seule ligne au lieu de toute la fin du fichier à partir du To. J'ai essayé avec d'autres truc comme [[:cntrl:]] ou [[:print:]] à la place du . mais rien à faire.
Théoriquement, je pensais faire quelquechose comme ça pour chopper tout ce qu'il y a entre To: et le prochain : (donc la liste d'email) :
cat mail.txt | grep -e 'To:.*:' -o avec l'option U (PCRE_UNGREEDY) pour s'arrêter au premier caractère ":" rencontré ( http://expreg.com/options.php )
En fait, je pense que c'est parce que grep travaille ligne par ligne. o_O
Marsh Posté le 20-05-2006 à 21:52:11
Je confirme, sans passages de ligne ça marche
Code :
|
En fait, en bourrinant, on pourrait concaténer toutes les lignes des entêtes mail dans une variable et sur une seule ligne.
Sur cette chaine, on execute : grep -e 'To:.*:' -o
Après on utile cut, on prend comme délimiteur : et on récupère la deuxième partie qui contient tous les e-mail suivi de Subject.
Après, on extrait les adresses e-mail avec la commande donnée dans mon post précédent.
Voilà, ça me semble très crad, je connais pas spécialement bash
Marsh Posté le 21-05-2006 à 04:08:40
grep n'est vraiment pas adapté pour résoudre ce problème.
Donc je propose d'utiliser sed (ok, je l'admet, j'utilise sed pour à peu près tout faire. Si j'avais un script pour faire mon café, il serait probablement en sed. Mais ça n'empêche pas que sed, c'est bien )
Dans un fichier (disons extract_to:_field.sed) :
/^To:/ { |
ensuite:
sed -nf extract_to:_field.sed nom_fichier_a_traiter |
Sur l'exemple, ça donne comme résultat :
To: moi@domain.com, toto@domain2.com, toto2@domain3.com, fgdfg@domain4.com, tructruc@domain5.com, luilui@domain5.com |
(c'est le seul test que j'ai fait. Il faut donner plus d'exemples si vous cherchez des comportements un peu tordus )
Sed utilise deux buffers : le pattern space, qui contient la ligne en cours de traitement, et le hold space, qui permet de sauvegarder des résultats précédents.
Rajoutons des commentaires :
Code :
|
Regardons ce qu'il se passe lorsqu'on exécute le script sur l'exemple.
sed lit les lignes une à une. il ne fait rien tant qu'on ne rencontre pas de lignes qui commence par "To:". Lorsqu'on en rencontre une (on est à la ligne 1), on entre dnas le bloc de code. On met le contenu du pattern space dans le hold space (ligne 2). Ils contiennent donc :
pattern space = To: moi@domain.com, toto@domain2.com,
hold space = To: moi@domain.com, toto@domain2.com,
On arrive en ligne 3, on execute la commande sed n, c'est à dire que l'on lit la ligne suivante, et qu'on la met dans le pattern space. Le hold space ne change pas.
pattern space = toto2@domain3.com, fgdfg@domain4.com,
hold space = To: moi@domain.com, toto@domain2.com,
En ligne 4, on a une étiquette appellée "loop" (on peut utiliser n'importe quel nom, bien sûr). Ça ne modifie évidemment pas les buffers.
En ligne 5, on regarde si le pattern space commence par un blanc. Si c'est le cas, on entre dnas le bloc qui suit (entre la ligne 5 et 9).
C'est effectivement ce qui se produit dans notre exemple.
En ligne 6, on ajoute le contenu du pattern space au hold space. Entre ce que contenait auparavant le hold space et ce qui est ajouté, sed ajoute un retour à la ligne, \n.
pattern space = toto2@domain3.com, fgdfg@domain4.com,
hold space = To: moi@domain.com, toto@domain2.com,\n toto2@domain3.com, fgdfg@domain4.com,
En ligne 7, on lit la ligne suivante, et on la met dans le pattern space. Le hold space ne change pas.
pattern space = tructruc@domain5.com, luilui@domain5.com
hold space = To: moi@domain.com, toto@domain2.com,\n toto2@domain3.com, fgdfg@domain4.com,
En ligne 8, on a un branchement. On "saute" à l'étiquette appellée "loop" (bref : on boucle).
On arrive en ligne 5, et on vérifie de nouveau si le pattern space commence par un blanc. C'est le cas, on entre dans le bloc.
En ligne 6 et 7, on refait la même chose que précédemment. On a alors :
pattern space = Subject: truc
hold space = To: moi@domain.com, toto@domain2.com,\n toto2@domain3.com, fgdfg@domain4.com,\n tructruc@domain5.com, luilui@domain5.com
En ligne 8, on boucle de nouveau.
En ligne 5, on regarde encore une fois si le pattern space commence par un blanc. Ce n'est pas le cas cette fois ci : on n'entre pas dans le bloc.
On arrive ligne 15. On execute la commande sed x, qui échange le contenu du pattern sapce et du hold space. (note : dans ce cas précis, on aurait pu utiliser la commande g, qui copie le contenu du hold space dans le pattern space, cela n'aurait rien changé). On a donc :
pattern space = To: moi@domain.com, toto@domain2.com,\n toto2@domain3.com, fgdfg@domain4.com,\n tructruc@domain5.com, luilui@domain5.com
hold space = Subject: truc
En ligne 16, on enlève les retours à la ligne du pattern space. La commande s remplace ce qui est matché entre les deux premiers slashs (ici : \n, le retour à la ligne) par ce qui est entre le deuxième et le troisième slash (ici, un simple espace). Le g signifie que l'on veut remplacer toutes les occurences de l'expression : si on ne le met pas, sed n'enlèverait que le premier \n.
pattern space = To: moi@domain.com, toto@domain2.com, toto2@domain3.com, fgdfg@domain4.com, tructruc@domain5.com, luilui@domain5.com
En ligne 17, on enlève les espaces superflus. + signifie "une fois ou plus". Il faut le protéger avec un antislash.
pattern space = To: moi@domain.com, toto@domain2.com, toto2@domain3.com, fgdfg@domain4.com, tructruc@domain5.com, luilui@domain5.com
En ligne 18, on demande d'afficher le pattern space. Lors de l'appel à sed, on a utilisé le drapeau -n, pour qu'il n'affiche rien par défaut (si on ne le met pas, sed affiche le contenu du pattern space a chaque fois qu'il arrive en bas du script).
En ligne 19, on demande à sed d'arrêter de traiter le fichier immédiatement.
Le script fait quelques suppositions qui peuvent poser problèmes; en particulier, il considère que les lignes du champs To: sont indentés lorsqu'il s'étend sur plusieurs lignes, et que la ligne suivant ce champ ne commence pas par un caractère d'espacement. Il faut aussi qu'il n'y ait pas de lignes qui commencent par "To:" avant celle qui nous intéresse, et corrolaire, il ne peu pas y avoir plusieurs champs "To:". Ça me semble plutôt raisonnable, mais j'ignore si c'est valide, et je n'ai franchement pas envie de subir la/les RFCs adéquates
Marsh Posté le 21-05-2006 à 12:12:49
Normalement, il n'y a qu'un seul champ to:
Je ne connaissais pas sed (du moins, jamais vu d'exemple de fonctionnement), et ça a l'air puissant je vais m'y mettre à la prochaine occasion.
Marsh Posté le 21-05-2006 à 16:34:36
merci beaucoup oh grand maitre du Sed
ça marche nickel!
je savais que c'était un outil puissant mais je savais pas du tout comment ça marchait.
Marsh Posté le 21-05-2006 à 19:35:23
à l'arrache et non testé :
|
Marsh Posté le 21-05-2006 à 19:40:43
black_lord a écrit : à l'arrache et non testé :
|
non ça ne peut pas marcher car la réponse peut etre en plusieurs lignes et si on fait un simple grep ^To:, on ne récupère que la première ligne.
Marsh Posté le 21-05-2006 à 19:45:16
j'avais dit "à l'arrache"
Marsh Posté le 21-05-2006 à 19:48:41
black_lord a écrit : j'avais dit "à l'arrache" |
remarque ça marche plus ou moins mais seulement quand il y pas trop de destinataires et que ça tient sur une seule ligne.
donc c'est pas entièrement faux
Marsh Posté le 19-05-2006 à 18:19:32
Bonjour,
J'essaye de faire un script bash mais je n'arrive pas à faire ce que je veux. Et c'est peut etre très simple alors si quelqu'un a une solution, je serais bien content.
Voilà, j'ai un fichier (c'est un email brut), qui contient plein de texte dont la chose suivante :
J'ai besoin de récuperer l'ensemble des lignes après "To :" (en sachant que le nombre de lignes est variable et la derniere ligne n'a pas de virgule à la fin).
J'imagine que c'est faisable simplement mais je ne suis pas un pro du bash.
Merci d'avance