un ptit peu d'aide en Bash

un ptit peu d'aide en Bash - Codes et scripts - Linux et OS Alternatifs

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 :

Code :
  1. texte bla bla
  2. To: destin@domain1.com, destin2@domaine2.com,
  3.        destinataire3@domain3.com,
  4.        destinataire4@domain3.com
  5. texte bla bla


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
 
 

Reply

Marsh Posté le 19-05-2006 à 18:19:32   

Reply

Marsh Posté le 19-05-2006 à 18:25:39    

une soluc un peu differente
cat tonfichier.txt | mail tes@destinataire.com

Reply

Marsh Posté le 19-05-2006 à 18:29:57    

dchost99 a écrit :

une soluc un peu differente
cat tonfichier.txt | mail tes@destinataire.com


 
quel rapport ?  :??: sachant que je ne connais justement pas les destinataire mais que je veux les lister

Reply

Marsh Posté le 19-05-2006 à 18:31:29    

oups, pas bien lu...

Reply

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


---------------
Celui qui pose une question est idiot 5 minutes. Celui qui n'en pose pas le reste toute sa vie. |  Membre du grand complot pharmaceutico-médico-scientifico-judéo-maçonnique.
Reply

Marsh Posté le 19-05-2006 à 19:08:09    

oui mais il reste encore bcp de lignes après ...

Reply

Marsh Posté le 20-05-2006 à 14:05:12    

le poste de Mjules répond à ta question non ? Sinon, sois plus explicite stp.

Reply

Marsh 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

Reply

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

Reply

Marsh Posté le 20-05-2006 à 21:52:11    

Je confirme, sans passages de ligne ça marche  
 

Code :
  1. echo ".... To: moi@domain.com, toto@domain2.com, toto2@domain3.com, fgdfg@domain4.com, tructruc@domain5.com, luilui@domain5.com Subject: truc " | grep -e 'To:.*:' -o
  2. To: moi@domain.com, toto@domain2.com, toto2@domain3.com, fgdfg@domain4.com, tructruc@domain5.com, luilui@domain5.com Subject:


 
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 :)

Reply

Marsh Posté le 20-05-2006 à 21:52:11   

Reply

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 [:chrisbk] )
 
 
Dans un fichier (disons extract_to:_field.sed) :

/^To:/ {
 h            
 n
 :loop
 /^[[:blank:]]/ {
  H
  n
  b loop
 }
 
 x
 s/\n/ /g
 s/[[:blank:]]\+/ /g
 p
 q
}


 
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 :o )
 
 
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 :
  1. /^To:/ {
  2.        h               # on met le contenu du pattern space (cad, la ligne qui commence par "To:" ) dans le hold space
  3.        n               # on met la ligne suivante dans le pattern space
  4.        :loop
  5.        /^[[:blank:]]/ {        # si la ligne commence par un blanc
  6.                H               # on concatène la ligne courante au hold space existant
  7.                n               # on met la ligne suivante dans le pattern space
  8.                b loop          # on boucle en retournant a l'etiquette loop
  9.        }
  10.        # on arrive ici lorsque la ligne ne commence pas par un blanc
  11.        # le hold space contient la totalite du champ To:, avec éventuellement
  12.        # des retours à la ligne.
  13.        x               # on échange le contenu du hold et du pattern space
  14.        s/\n/ /g        # on enlève tous les retours à la ligne
  15.        s/[[:blank:]]\+/ /g     # on enlève des espaces inutiles
  16.        p                       # on affiche le résultat
  17.        q                       # on quitte sed, ce qui nous évite des désagréments
  18.                                # s'il y avait des lignes commençant par To: plus bas
  19. }


 
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 :D

Reply

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.

Reply

Marsh Posté le 21-05-2006 à 16:34:36    

merci beaucoup oh grand maitre du Sed  :D  
ça marche nickel!
 
je savais que c'était un outil puissant mais je savais pas du tout comment ça marchait.

Reply

Marsh Posté le 21-05-2006 à 19:35:23    

à l'arrache et non testé :


grep ^To: fichier | cut -d':' -f2


---------------
uptime is for lousy system administrators what Viagra is for impotent people - mes unixeries - github me
Reply

Marsh Posté le 21-05-2006 à 19:40:43    

black_lord a écrit :

à l'arrache et non testé :


grep ^To: fichier | cut -d':' -f2



 
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.

Reply

Marsh Posté le 21-05-2006 à 19:45:16    

j'avais dit "à l'arrache" :o
 
:D


---------------
uptime is for lousy system administrators what Viagra is for impotent people - mes unixeries - github me
Reply

Marsh Posté le 21-05-2006 à 19:48:41    

black_lord a écrit :

j'avais dit "à l'arrache" :o
 
:D


 
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  :)

Reply

Sujets relatifs:

Leave a Replay

Make sure you enter the(*)required information where indicate.HTML code is not allowed