Bash : Substitution de variables dans un fichier

Comment substituer des variables dans un fichier depuis un script Bash ?
Comment utiliser un modèle, template ou typon dans un script Bash ?

Une méthode élégante : envsubst

« envsubst » Est un programme de « gettext » destiné à substituer des variables d’environnement par leur valeur dans une chaîne de caractères.

Le fait que le programme ne s’attache qu’aux variables d’environnement nous obligera à exporter les paramètres à substituer.

En utilisation directe dans le shell cela donne :

fhh@aaricia ~/tmp $ cat > typon.txt
Salut ${NOM},
 
Voici un message de "${expediteur}" contenant :
 
${chaine}
 
fhh@aaricia ~/tmp $ NOM=FHH ; expediteur=admin-linux.fr ; chaine="C'est pas beau tout ça ?" ;
fhh@aaricia ~/tmp $ export NOM expediteur chaine
fhh@aaricia ~/tmp $ envsubst < typon.txt
Salut FHH,
 
Voici un message de "admin-linux.fr" contenant :
 
C'est pas beau tout ça ?
 
fhh@aaricia ~/tmp $ unset NOM expediteur chaine
  • la première commande crée un simple fichier texte qui servira de modèle (typon ou « template« ) ;
  • des valeurs sont données aux variables utilisées dans le modèle ;
  • les variables sont exportées :
  • le modèle est passé à « envsubst » qui y remplace les variables par leurs valeurs et affiche le résultat ;
  • les variables sont libérées.

Exemple de script

À titre d’exemple, voici un script destiné à envoyer à chaque utilisateurs un mail dont le contenu est stocké dans le fichier « mail.txt ».
Les données des utilisateurs sont passées au script au format « /etc/passwd ».

1
2
3
4
5
6
7
8
#!/bin/bash
 
IFS=":"
while read _LOGIN mdp uid gid _NOM home shell ; do
        export _NOM _LOGIN ;
        envsubst < mail.txt | mail -s "${_NOM} votre compte sur $(hostname)" ${_LOGIN}@mydomain.com
        unset _LOGIN mdp uid gid _NOM home shell ;
done
  • ligne 3, remplacement d’IFS (voir « $IFS : Le séparateur standard du shell« ) ;
  • ligne 4, lecture des données utilisateur au format « /etc/passwd » ;
  • ligne 5, les variables à utiliser sont exportées ;
  • ligne 6, envsubst crée le message basé sur le typon « mail.txt » et l’envoie par mail à l’adresse « ${_LOGIN}@mydomain.com » avec comme sujet « Nom utilisateur votre compte sur la machine » ;
  • ligne 7, les variables sont libérées.

Le fichier « mail.txt » est un simple fichier texte :

fhh@aaricia ~/tmp $ cat mail.txt
Bonjour ${_NOM},
 
Vous recevez ce mail car vous disposez d'un compte (login : ${_LOGIN}) sur le domaine "mydomain.com".
 
Tout va bien ?
 
FHH

L’invocation du script est des plus simples :

fhh@aaricia ~/tmp $ getent passwd | awk -F':' '{ if($3 >= 1000) print $0 }' | \
> ./sendnotification.sh

Le mail contenu dans « mail.txt » est envoyé à tous les comptes ayant un uid supérieur ou égal à 1000.

Un classique : un balisage et sed

Autre méthode, créer un jeu de balise qui seront remplacées par « sed ».

À chaque variable utilisée, nous associons une balise au format de notre choix (de préférence qui ne ressemble à rien de connu exemple « <__nom__>« ) que nous plaçons dans le corps du fichier texte. Via « sed », les balises sont ensuite substituées par la valeur des variables associées.

Directement dans le shell cela donne :

fhh@aaricia ~/tmp $ cat > typon.sed.txt
Salut <__NOM__>,
 
Voici un message de "<__EXPEDITEUR__>" contenant :
 
<__CHAINE__>
 
fhh@aaricia ~/tmp $ NOM=FHH ; EXPEDITEUR=admin-linux.fr ; CHAINE="C'est pas beau tout ça ?" ;
fhh@aaricia ~/tmp $ sed -e "s/<__CHAINE__>/${CHAINE}/g;s/<__NOM__>/${NOM}/g;s/<__EXPEDITEUR__>/${EXPEDITEUR}/g" < typon.sed.txt
Salut FHH,
 
Voici un message de "admin-linux.fr" contenant :
 
C'est pas beau tout ça ?

Note : l’ordre de substitution des balise n’a pas d’importance.

Exemple de script

Le script proposé précédemment devient :

1
2
3
4
5
6
7
8
#!/bin/bash
 
IFS=":"
while read _LOGIN mdp uid gid _NOM home shell ; do
        sed -e "s/<__NOM__>/${_NOM}/g;s/<__LOGIN__>/${_LOGIN}/g" < mail.sed.txt | \
                mail -s "${_NOM} votre compte sur $(hostname)" ${_LOGIN}@mydomain.com
        unset _LOGIN mdp uid gid _NOM home shell ;
done

Le fichier « mail.sed.txt » reste au format texte mais contient désormais des balises :

Bonjour <__NOM__>,
 
Vous recevez ce mail car vous disposez d'un compte (login : <__LOGIN__>) sur le domaine "mydomain.com".
 
Tout va bien ?
 
FHH

L’invocation reste inchangée.

Laisser un commentaire

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