Linux bash shell extraction de chaine
Résolu
sbouli
Messages postés
200
Date d'inscription
Statut
Membre
Dernière intervention
-
BHeaDMaN -
BHeaDMaN -
Bonjour,
Je tente de developper un outil pour parser les logs postfix, je fais d'abord un
qui me permet de ne traiter que les bounces,
le but est d'écrire un fichier CSV à importer en bdd avec les champs :
un exemple de ligne du log est
Mon premier jet étais avec la commande sed sous la forme :
cependant, impossible d'obtenir une date correcte car l'année ne figure pas dans les logs et le format est un peu arbitraire ... ne pouvant facilement bricoler la date, j'ai changé mon fusil d'épaule en utilisant :
cependant, le champ destinataire est alors de la forme : to=<toto.toto@wanadoo.fr>, et pas seulement le mail ...
J'ai essayer de faire une fonction extract avec 3 paramètres, le premier la chaine, le second la chaine de debut (ici <) le troisième la chaine de fin (ici >) mais ça ne fonctionne pas ... :
Merci de me venir en aide soit en améliorant le sed pour pouvoir ajouter l'année (soit en cours soit l'année de création du fichier de log), soit en réussissant la fonction de découpe de chaine avec délimiteurs ...
A moins que vous n'ayez d'autre idées ?????
En vous remerciant
Stéphane
Je tente de developper un outil pour parser les logs postfix, je fais d'abord un
cat $D_LOGS/$v_fich | grep "status=bounced" > bounces.tmp
qui me permet de ne traiter que les bounces,
le but est d'écrire un fichier CSV à importer en bdd avec les champs :
nom_serveur, email, domaine, cause_bounce, date_badmail
un exemple de ligne du log est
Aug 20 08:57:00 serveurname postfix/smtp[1965]: 732DBD4C867: to=<toto.toto@wanadoo.fr>, relay=smtp.wanadoo.fr[193.252.22.78]:25, delay=0.1, delays=0.04/0/0.03/0.03, dsn=5.0.0, status=bounced (host smtp.wanadoo.fr[193.252.22.78] said: 550 <toto.toto@wanadoo.fr>: Recipient address rejected: User unknown (in reply to RCPT TO command))
Mon premier jet étais avec la commande sed sous la forme :
sed '/@/!d;s/^\(.*\)'$(hostname)'.*<\(.*@\(.*\)\)>.*bounced\(.*\)$/'$(hostname)'|\2|\3|\4|\1/' bounces.tmp >>$(hostname).csv
cependant, impossible d'obtenir une date correcte car l'année ne figure pas dans les logs et le format est un peu arbitraire ... ne pouvant facilement bricoler la date, j'ai changé mon fusil d'épaule en utilisant :
while IFS=$' ' read mois jour heure serveur process id destinataire relay delay delays dsn status infos do echo -e " mois : $mois \n\ jour : $jour \n\ heure : $heure \n\ serveur : $serveur \n\ process : $process \n\ id : $id \n\ destinataire : $destinataire \n\ relay : $relay \n\ delay : $delay \n\ delays : $delays \n\ dsn : $dsn \n\ status : $status \n\ infos : $infos \n"; done < bounces.tmp
cependant, le champ destinataire est alors de la forme : to=<toto.toto@wanadoo.fr>, et pas seulement le mail ...
J'ai essayer de faire une fonction extract avec 3 paramètres, le premier la chaine, le second la chaine de debut (ici <) le troisième la chaine de fin (ici >) mais ça ne fonctionne pas ... :
extract() { local str deb fin temp str="${1:-''}" deb="${2:-'<'}" fin="${3:-'>'}" $temp = echo ${str#*$deb} $temp2 = echo ${temp%*$fin} return $temp2 }
Merci de me venir en aide soit en améliorant le sed pour pouvoir ajouter l'année (soit en cours soit l'année de création du fichier de log), soit en réussissant la fonction de découpe de chaine avec délimiteurs ...
A moins que vous n'ayez d'autre idées ?????
En vous remerciant
Stéphane
A voir également:
- Linux bash shell extraction de chaine
- Classic shell - Télécharger - Personnalisation
- Chaine tnt gratuite sur mobile - Guide
- Plus de chaine tv - Guide
- Linux reader - Télécharger - Stockage
- Chaine radio - Télécharger - Médias et Actualité
5 réponses
Tiens essayes ça :
[tmpfs]$ cat fich Aug 20 08:57:00 serveurname postfix/smtp[1965]: 732DBD4C867: to=<toto.toto@wanadoo.fr>, relay=smtp.wanadoo.fr[193.252.22.78]:25, delay=0.1, delays=0.04/0/0.03/0.03, dsn=5.0.0, status=bounced (host smtp.wanadoo.fr[193.252.22.78] said: 550 <toto.toto@wanadoo.fr>: Recipient address rejected: User unknown (in reply to RCPT TO command)) Aug 22 09:57:00 monserveur postfix/smtp[1965]: 732DBD4C867: to=<titi.titi@free.fr>, relay=smtp.free.fr[193.252.22.78]:25, delay=0.1, delays=0.04/0/0.03/0.03, dsn=5.0.0, status=bounced (host smtp.free.fr[193.252.22.78] said: 550 <titi.titi@free.fr>: Recipient address rejected: User unknown (in reply to RCPT TO command)) [tmpfs]$ cat foo.sh #! /bin/bash while read line do cause=$(awk -F"(" '{ print "("$2"("$3 }' <<<$line) DATE=$(awk '{ print $1,$2,$3 }' <<<$line) NEW_DATE=$(date --date="${DATE}" '+%d/%m/%Y %H:%M:%S') NEW_line=$(awk '{ print $4","$7$12"," }' <<<$line | sed 's/to=<//;s/>//') sed "s|\(.*@\)\([^,]*\)\(.*\)|\1\2,\2,${cause},${NEW_DATE}|" <<<$NEW_line done < fich [tmpfs]$ ./foo.sh serveurname,toto.toto@wanadoo.fr,wanadoo.fr,(host smtp.wanadoo.fr[193.252.22.78] said: 550 <toto.toto@wanadoo.fr>: Recipient address rejected: User unknown (in reply to RCPT TO command)),20/08/2008 08:57:00 monserveur,titi.titi@free.fr,free.fr,(host smtp.free.fr[193.252.22.78] said: 550 <titi.titi@free.fr>: Recipient address rejected: User unknown (in reply to RCPT TO command)),22/08/2008 09:57:00 [tmpfs]$;-))
Salut,
Une idée peut être...
Une idée peut être...
$ cat fich Aug 20 08:57:00 serveurname postfix/smtp[1965]: 732DBD4C867: to=<toto.toto@wanadoo.fr>, relay=smtp.wanadoo.fr[193.252.22.78]:25, delay=0.1, delays=0.04/0/0.03/0.03, dsn=5.0.0, status=bounced (host smtp.wanadoo.fr[193.252.22.78] said: 550 <toto.toto@wanadoo.fr>: Recipient address rejected: User unknown (in reply to RCPT TO command)) $ awk '{ print $4","$7$12","$1,$2,$3 }' fich | sed 's/to=<//;s/>//' serveurname,toto.toto@wanadoo.fr,status=bounced,Aug 20 08:57:00:-))
Hello,
Incroyable, quand je pense que je rame depuis perpette la dessus ...
Si je pouvais abuser ... comment avoir plutot :
serveur_name,email,domaine,cause,date_heure
serveur_name = ça c'est déjà ok
email = ça c'est déjà ok
domaine = extraction du domaine du mail ... (à partir de @)
cause = tout ce qui suit status=bounced
date_heure = au format DD/MM/YYYY HH:MM:SS ou YYYYMMDD HHMMSS
Moi je sature sur toutes ces commandes à 8000 attributs et autre expression régulières qui se chevauchent ....
Au secours ....
Stéphane
Incroyable, quand je pense que je rame depuis perpette la dessus ...
Si je pouvais abuser ... comment avoir plutot :
serveur_name,email,domaine,cause,date_heure
serveur_name = ça c'est déjà ok
email = ça c'est déjà ok
domaine = extraction du domaine du mail ... (à partir de @)
cause = tout ce qui suit status=bounced
date_heure = au format DD/MM/YYYY HH:MM:SS ou YYYYMMDD HHMMSS
Moi je sature sur toutes ces commandes à 8000 attributs et autre expression régulières qui se chevauchent ....
Au secours ....
Stéphane
Euuu encore moi, suis toujours dessus ...
J'essais de mettre en place un tableau associatif pour changer le mois par son numéro exemple Aug devient 08
J'ai trouvé cette doc (ici : http://www.c-sait.net/cours/bash.php )
Donc je fais :
et j'obtiens TOUJOURS :
echo "numéro du mois ${Mois[Aug]}"
>numéro de mois 10
echo "numéro du mois ${Mois['Aug']}"
>numéro de mois 10
...GRRR....
J'essais de mettre en place un tableau associatif pour changer le mois par son numéro exemple Aug devient 08
J'ai trouvé cette doc (ici : http://www.c-sait.net/cours/bash.php )
Pour créer un tableau en n'utilisant pas les indices par défaut, on utilisera la syntaxe suivante : > tableau2=([clé0]=valeur0 [clé1]=valeur1 [clé2]=valeur2) Où les clés peuvent être n'importe quelles chaînes de caractères. A un tableau créé avec les index numériques par défaut, on peut très bien ajouter un élément dont la clé est une chaîne de caractères.
Donc je fais :
Mois=(["Jan"]="01" ["Fev"]="02" ["Aug"]="08" ["Sep"]="09" ["Oct"]="10"); ou Mois=([Jan]="01" [Fev]="02" [Aug]="08" [Sep]="09" [Oct]="10");
et j'obtiens TOUJOURS :
echo "numéro du mois ${Mois[Aug]}"
>numéro de mois 10
echo "numéro du mois ${Mois['Aug']}"
>numéro de mois 10
...GRRR....
Bonjour,
Cela fait un moment que ce post est terminé mais afin d'éviter cet écueil au débutant voici les réponses aux question de Sbouli.
Aux dernières nouvelle le langage "shell" ou "sh" ne sais pas gérer de variable à 2 profondeurs (ou tableau avec clé+valeur) à l'instar d'un langage comme perl ou python par exemple.
En suite pour faire une correspondance entre Mois et numéros il y a plusieurs solutions, voici les 2 que j'utilise :
1) un CASE .. IN .. ESAC
case $MOUNTH in
janv) MOUNTH=01 ;;
fev) MOUNTH=02 ;;
mars) MOUNTH=03 ;;
avr) MOUNTH=04 ;;
mai) MOUNTH=05 ;;
juin) MOUNTH=06 ;;
juil) MOUNTH=07 ;;
aou) MOUNTH=08 ;;
sept) MOUNTH=09 ;;
oct) MOUNTH=10 ;;
nov) MOUNTH=11 ;;
dec) MOUNTH=12 ;;
*) MOUNTH=13 ;;
esac
Je gère les erreurs en retournant la valeur "13" que je test dans un IF THEN FI
if [[ $MOUNTH -gt 12 ]]; then
Echo "Erreur de syntaxe"
exit 1
else
echo "Le numéros du mois est "$MOUNTH
fi
2) de façon intercative avec un Select (un poile plus complexe)
PS3="Choisir un Mois :"
select term in \
'Janvier' \
'Fevrier' \
'Mars' \
'Avril' \
'Mai' \
'Juin' \
'Juillet' \
'Aout' \
'Septembre' \
'Octobre' \
'Novembre' \
'Decembre' \
do
case $term in
Janvier) Mounth="01" ;;
Fevrier) Mounth="02" ;;
Mars) Mounth="03" ;;
Avril) Mounth="04" ;;
Mai) Mounth="05" ;;
Juin) Mounth="06" ;;
Juillet) Mounth="07" ;;
Aout) Mounth="08" ;;
Septembre) Mounth="09" ;;
Octobre) Mounth="10" ;;
Novembre) Mounth="11" ;;
Decembre) Mounth="12" ;;
esac
if [[ -n $term ]] ; then
echo $Mounth
break
fi
done
Ce code fonctionne en l'état il sufit de faire un copié coller et de tester ;-).
La commande "select" génère une liste de numéros (ici de 1 à 12) avec la valeur de chaque option, en suite le case (le même que précédemment) effectue un test afin d'attribuer la valeur voulu au mois. "SELECT" est une boucle, tant qu'une valeur non valide est renseigner la boucle est rejoué.
PS : Avec la fonction "SELECT" il est possible de récupérer au choix :
la valeur de l'option, ici contenu dans la variable "$term". Dans mon exemple la valeur de l'option pour le choix N°4 sera "Avril" (term="Avril").
ou
le numéros de la sélection via la variable $REPLY, cette variable est native de la fonction. Dans mon exemple le numéros de la sélection pour "Avril" sera 4 car celui-ci est en 4ème position.
Cela fait un moment que ce post est terminé mais afin d'éviter cet écueil au débutant voici les réponses aux question de Sbouli.
Aux dernières nouvelle le langage "shell" ou "sh" ne sais pas gérer de variable à 2 profondeurs (ou tableau avec clé+valeur) à l'instar d'un langage comme perl ou python par exemple.
En suite pour faire une correspondance entre Mois et numéros il y a plusieurs solutions, voici les 2 que j'utilise :
1) un CASE .. IN .. ESAC
case $MOUNTH in
janv) MOUNTH=01 ;;
fev) MOUNTH=02 ;;
mars) MOUNTH=03 ;;
avr) MOUNTH=04 ;;
mai) MOUNTH=05 ;;
juin) MOUNTH=06 ;;
juil) MOUNTH=07 ;;
aou) MOUNTH=08 ;;
sept) MOUNTH=09 ;;
oct) MOUNTH=10 ;;
nov) MOUNTH=11 ;;
dec) MOUNTH=12 ;;
*) MOUNTH=13 ;;
esac
Je gère les erreurs en retournant la valeur "13" que je test dans un IF THEN FI
if [[ $MOUNTH -gt 12 ]]; then
Echo "Erreur de syntaxe"
exit 1
else
echo "Le numéros du mois est "$MOUNTH
fi
2) de façon intercative avec un Select (un poile plus complexe)
PS3="Choisir un Mois :"
select term in \
'Janvier' \
'Fevrier' \
'Mars' \
'Avril' \
'Mai' \
'Juin' \
'Juillet' \
'Aout' \
'Septembre' \
'Octobre' \
'Novembre' \
'Decembre' \
do
case $term in
Janvier) Mounth="01" ;;
Fevrier) Mounth="02" ;;
Mars) Mounth="03" ;;
Avril) Mounth="04" ;;
Mai) Mounth="05" ;;
Juin) Mounth="06" ;;
Juillet) Mounth="07" ;;
Aout) Mounth="08" ;;
Septembre) Mounth="09" ;;
Octobre) Mounth="10" ;;
Novembre) Mounth="11" ;;
Decembre) Mounth="12" ;;
esac
if [[ -n $term ]] ; then
echo $Mounth
break
fi
done
Ce code fonctionne en l'état il sufit de faire un copié coller et de tester ;-).
La commande "select" génère une liste de numéros (ici de 1 à 12) avec la valeur de chaque option, en suite le case (le même que précédemment) effectue un test afin d'attribuer la valeur voulu au mois. "SELECT" est une boucle, tant qu'une valeur non valide est renseigner la boucle est rejoué.
PS : Avec la fonction "SELECT" il est possible de récupérer au choix :
la valeur de l'option, ici contenu dans la variable "$term". Dans mon exemple la valeur de l'option pour le choix N°4 sera "Avril" (term="Avril").
ou
le numéros de la sélection via la variable $REPLY, cette variable est native de la fonction. Dans mon exemple le numéros de la sélection pour "Avril" sera 4 car celui-ci est en 4ème position.
Vous n’avez pas trouvé la réponse que vous recherchez ?
Posez votre question