Pages : 1
#1 Le 24/03/2008, à 12:29
- sebg38
Récupérer en-tête mail - sed ?
Bonjour,
Je souhaite envoyer une liste des messages classés spam. Pour cela, je voudrais récupérer une partie des en-tête des messages : les champs From, Subject et X-TRASH dans cette ordre et si ils existent.
Un exemple vaut mieux qu'un long discours. Si le fichier de mail contient :
From: Toto <toto@toto.fr>
To: Tata <tata@tata.fr>
Subject: FELICITATION
X-TRASH: Regle 1
blabla
Subject: Bonjour
From: Tata <tata@tata.fr>
To: Toto <toto@toto.fr>
blabla
Je voudrais obtenir :
-- De : Toto <toto@toto.fr>
Objet : FELICITATION
Règle : Regle 1
-- De : Tata <tata@tata.fr>
Objet : Bonjour
Pour le moment, j'utilise (le fichier s'appelle Spam) :
grep -Ei '^(From:|Subject:|X-TRASH:)' Spam | sed -e "s/^From:/ -- De : /;s/^Subject:/ Objet : /;s/^X-TRASH:/ Règle : /"
mais évidemment ça ne marche pas car les champs From: et Subject: ne sont pas dans le bon ordre pour le 2ième mail. J'obtiens :
-- De : Toto <toto@toto.fr>
Objet : FELICITATION
Règle : Regle 1
Objet : Bonjour
-- De : Tata <tata@tata.fr>
J'ai cherché un peu mais j'avoue que je ne suis pas un pro du sed ...
Si vous avez des idées, je suis preneur. D'avance merci,
seb
Hors ligne
#2 Le 24/03/2008, à 19:09
- Saito
Re : Récupérer en-tête mail - sed ?
Bonjour,
je n'ai pas trouvé de one-liner avec sed ( quoique ce soit peut-être faisable ) mais à la place j'ai fait un script bash qui donne bien la sortie que tu veux.
#!/bin/bash
from=
subject=
regle=
echo Traitement du fichier "$1"...
function formatage
{
echo -e "$@" | sed -e "s/^From:/ -- De : /;s/^Subject:/ Objet : /;s/^X-TRASH:/ Règle : /"
}
while read line
do
[[ $from != '' && $subject != '' ]] && \
[[ $line == From:* || $line == Subject:* ]] && \
formatage $from"\n"$subject"\n"$regle"\n" && \
{ from= ; subject= ; regle= ;}
case $line in
From:*) [[ -z $from ]] && from=$line
;;
Subject:*) [[ -z $subject ]] && subject=$line
;;
X-TRASH:*) [[ -z $regle ]] && regle=$line
;;
esac
done < <(grep -Ei '^(From:|Subject:|X-TRASH:)' "$1")
formatage $from"\n"$subject"\n"$regle"\n"
exit 0
Ca vaut ce que ça vaut, teste-le et vois si ça te convient
( Tu dois passer le nom du fichier que tu veux traiter comme premier argument, «./mon_script.sh mes_mails» )
Aku-Soku-Zan_Shinsengumi
Hors ligne
#3 Le 25/03/2008, à 01:16
- Laurent82
Re : Récupérer en-tête mail - sed ?
astucieuse l'idée Saito !
Si vous voulez vraiment du one-liner, c'est possible avec awk (en reprenant l'idée de Saito):
awk '$1 ~ /^(From:|Subject:|X-TRASH:)/ {from="--De :" ; trash="\tRègle :" ; subject="\tObjet :" ; sub("From:",from); sub("Subject:",subject); sub("X-TRASH:",trash) ; if((de!="" && objet!="")&&($0 ~ from"|"subject)) {global=global"\n"de"\n"objet"\n"regle"\n" ; de="";objet=""; regle=""} ; if($0 ~ from) de=$0 ; else if($0 ~ subject) objet=$0 ; else regle=$0 } END { print global"\n"de"\n"objet"\n"regle }' Spam
Bah quoi
Blague à part, une fois mis en forme et écrit correctement, il y a des chances que l'opération soit un peu plus rapide avec awk
#4 Le 25/03/2008, à 11:31
- sebg38
Re : Récupérer en-tête mail - sed ?
Excellente idée Saito, c'est exactement ce que je voulais. Merci. Je n'avais même pas penser à faire un script bash. J'ai juste modifié un peu pour ne pas avoir de \n quand le champ n'est pas présent. Ça marche parfaitement.
Je n'ai pas encore regardé et déchiffré la proposition one-liner de Laurent. Je vais regarder ça.
Sinon, j'ai une question un peu similaire. Comment remplacer tous les _ par des espaces uniquement s'ils sont compris entre deux balises =? et ?=.
Un exemple :
=?to_to_to?= to_to
doit donner
=?to to to?= to_to
J'ai essayé plusieurs trucs dont
echo -e "=?to_to_to?= to_to" | sed -e 's/=?\([^`?=`]*\)_\([^'?=']*\)?=/=?\1 \2?=/g'
et
echo -e "=?to_to_to?= to_to" | sed -e 's/=?\([^`=?`]*\)_/=?\1 /g'
et à chaque fois ça ne marche pas, ça ne remplace que le dernier _, j'obtiens
=?to_to to?= to_to
Cà doit être tout bête mais je ne vois pas. Des idées ?
seb
Hors ligne
#5 Le 25/03/2008, à 11:35
- Laurent82
Re : Récupérer en-tête mail - sed ?
Saito (ou les autres bien sûr)
Sais-tu pourquoi si je remplace dans ton script :
< <(grep -Ei '^(From:|Subject:|X-TRASH:)' "$1")
par
grep -Ei '^(From:|Subject:|X-TRASH:)' "$1" | while read line
ça ne fonctionne plus bien ? En fait ça fonctionne sauf pour le dernier message qui passe à la trappe.
Pourtant en théorie le résultat devrait être le même non ?
#6 Le 25/03/2008, à 14:51
- Alain.g
Re : Récupérer en-tête mail - sed ?
Bonjour
Sinon, j'ai une question un peu similaire. Comment remplacer tous les _ par des espaces uniquement s'ils sont compris entre deux balises =? et ?=.
Avec perl :
echo =?to_to_to?= to_to | perl -pe 's/=\?.*?\?=/($a=$&)=~s,_, ,g,$a/eg'
Si les balises ouvrante et fermante peuvent être sur une ligne différente, il faut passer un "mode" multi-ligne avec -0777 (tout le fichier comme une ligne) ou -00 (paragraphe comme une seule ligne) par exemple
echo -e "=?\nto_to_to\n?= to_to" | perl -0777pe 's/=\?.*?\?=/($a=$&)=~s,_, ,g,$a/seg'
Dernière modification par Alain.g (Le 31/03/2008, à 11:51)
Xubuntu Karmic !
Hors ligne
#7 Le 25/03/2008, à 15:00
- Saito
Re : Récupérer en-tête mail - sed ?
@Laurent82: Non c'est diffèrent ( et je me suis fait avoir aussi ) car bash exécute la partie droite d'un pipe dans un sous-shell (alors que pour zsh, mon shell de prédilection, c'est la partie gauche), du coup le dernier message que tu affiches étant extérieur à ce sous-shell, les variables sont telles qu'elles ont été définies en dehors du sous-shell, c'est-à-dire vides au début du script. Alors qu'avec le process substitution, c'est le grep qui sera lancé dans un sous-shell.
Sinon, joli one-big-liner avec awk!
@sebg38
J'ai une solution pour ton problème de toto, aimablement fournie par ramok sur le channel #sed de freenode que je remercie:
echo 'to_to =?to_to_to_?= to_to =?to_to_to?= to_to' | sed -e ':z;s/\(=*\)_\([^?]*?=\)/\1 \2/;tz'
A toi de choisir entre cette solution et celle en Perl d'Alain.g
Dernière modification par Saito (Le 25/03/2008, à 19:25)
Aku-Soku-Zan_Shinsengumi
Hors ligne
#8 Le 25/03/2008, à 21:03
- Alain.g
Re : Récupérer en-tête mail - sed ?
J'avoue que je ne comprends pas complètement cette solution avec sed, je vais regarder de plus près, mais si elle fonctionne dans cet exemple précis, dès qu'on ajoute un point d'interrogation ça ne va plus :
Par exemple :
echo 'to_to =?to_to?_to_?= to_to' | sed -e ':z;s/\(=*\)_\([^?]*?=\)/\1 \2/;tz'
renvoie : to_to =?to_to? to ?= to_to
Dernière modification par Alain.g (Le 25/03/2008, à 22:14)
Xubuntu Karmic !
Hors ligne
#9 Le 25/03/2008, à 22:44
- Saito
Re : Récupérer en-tête mail - sed ?
Oui exact, j'ai modifié cette version et ça a l'air de mieux marcher:
echo 'to_to =?to_to?_to_?= to_to' | sed -e ':z;s/\(=?.*\)_\(.*?=\)/\1 \2/;tz'
Edit: Mea culpa, en fait j'ai fait une erreur de copie, la solution donnée par ramok était celle-ci.
Dernière modification par Saito (Le 25/03/2008, à 22:53)
Aku-Soku-Zan_Shinsengumi
Hors ligne
#10 Le 25/03/2008, à 23:37
- Alain.g
Re : Récupérer en-tête mail - sed ?
oui mais du coup ça ne fonctionne plus avec ton premier texte
echo 'to_to =?to_to_to_?= to_to =?to_to_to?= to_to' | sed -e ':z;s/\(=?.*\)_\(.*?=\)/\1 \2/;tz'
donne : to_to =?to to to ?= to to =?to to to?= to_to
Xubuntu Karmic !
Hors ligne
#11 Le 26/03/2008, à 00:24
- Saito
Re : Récupérer en-tête mail - sed ?
Hihi, en effet, par défaut les quantifieurs de sed sont greedy, et il n'y pas moyen de les rendre stingy... Donc à priori, on ne peut traiter ce cas qu'en modifiant ainsi:
echo 'to_to =?to_to_to_?= to_to =?to_to_to?= to_to' | sed -e ':z;s/\(=?.*\)_\([^?]*?=\)/\1 \2/;tz'
ce qui revient presque à ce que j'avais dis avant mais qui ne convient toujours pas si il y existe un «?» entre =? et ?=. Mais c'est le seul moyen d'éviter que le premier «.*» ne mange tout.
Dernière modification par Saito (Le 26/03/2008, à 00:27)
Aku-Soku-Zan_Shinsengumi
Hors ligne
#12 Le 26/03/2008, à 22:41
- sebg38
Re : Récupérer en-tête mail - sed ?
Bonjour,
Merci pour toutes vos réponses. Ma deuxième question n'était donc pas si simple que ça, et pour le coup perl est gagnant par rapport à sed. Je ne connais pas du tout perl, il va falloir que je m'y mette, ça m'a l'air vraiment efficace. Vous connaissez un bon tuto pour commencer ?
seb
Hors ligne
#13 Le 27/03/2008, à 11:04
- philou8237
Re : Récupérer en-tête mail - sed ?
oui : http://sylvain.lhullier.org/publications/perl.html
Bonne doc, bien rédigée (en meme temps c'est sylvain qu'il l'a faite alors bon....)
Hors ligne
#14 Le 27/03/2008, à 21:54
- sebg38
Re : Récupérer en-tête mail - sed ?
Merci, c'est noté.
Hors ligne