Solution 1 :
C'est très possible. Un moyen très simple d'implémenter cela serait que le fichier de modèle soit en fait le script et utilise des variables shell telles que
#! /bin/bash
version="1.2.3"
path="/foo/bar/baz"
cat > /tmp/destfile <<-EOF
here is some config for version $version which should
also reference this path $path
EOF
Vous pouvez même rendre cela configurable sur la ligne de commande en spécifiant version=$1
et path=$2
, vous pouvez donc l'exécuter comme bash script /foo/bar/baz 1.2.3
. Le -
avant qu'EOF ne provoque des espaces avant que les lignes ne soient ignorées, utilisez simplement <<EOF
si vous ne voulez pas ce comportement.
Une autre façon de procéder serait d'utiliser la fonctionnalité de recherche et de remplacement de sed
#! /bin/bash
version="1.2.3"
path="/foo/bar/baz"
sed -e "s/VERSION/$version/g" -e "s/PATH/$path/" /path/to/templatefile > /tmp/destfile
qui remplacerait chaque instance des chaînes VERSION et PATH. S'il y a d'autres raisons pour lesquelles ces chaînes se trouveraient dans le fichier de modèle, vous pouvez faire en sorte que votre recherche et remplacement soit VERSION ou %VERSION% ou quelque chose de moins susceptible d'être déclenché accidentellement.
Solution 2 :
Le moyen le plus simple de le faire simplement dans Linux CLI est d'utiliser envsubst
et variables d'environnement.
Exemple de fichier modèle apache.tmpl
:
<VirtualHost *:${PORT}>
ServerName ${SERVER_NAME}
ServerAlias ${SERVER_ALIAS}
DocumentRoot "${DOCUMENT_ROOT}"
</VirtualHost>
Exécutez envsubst
et afficher le résultat dans un nouveau fichier my_apache_site.conf
:
export PORT="443"
export SERVER_NAME="example.com"
export SERVER_ALIAS="www.example.com"
export DOCUMENT_ROOT="/var/www/html/"
envsubst < apache.tmpl > my_apache_site.conf
Sortie :
<VirtualHost *:443>
ServerName example.com
ServerAlias www.example.com
DocumentRoot "/var/www/html/"
</VirtualHost>
Solution 3 :
Aucun outil nécessaire autre que /bin/sh
. Étant donné un fichier modèle du formulaire
Version: ${version}
Path: ${path}
ou même avec un code shell mixte inclus
Version: ${version}
Path: ${path}
Cost: ${cost}\$
$(i=1; for w in one two three four; do echo Param${i}: ${w}; i=$(expr $i + 1); done)
et un fichier de configuration analysable par le shell comme
version="1.2.3-r42"
path="/some/place/under/the/rainbow/where/files/dance/in/happiness"
cost="42"
c'est une simple question d'étendre cela à
Version: 1.2.3-r42
Path: /some/place/under/the/rainbow/where/files/dance/in/happiness
Cost: 42$
Param1: one
Param2: two
Param3: three
Param4: four
En effet, étant donné le chemin du fichier de configuration dans la variable shell config_file
et le chemin vers le fichier modèle en template_file
, il vous suffit de :
. ${config_file}
template="$(cat ${template_file})"
eval "echo \"${template}\""
C'est peut-être plus joli que d'avoir un script shell complet comme fichier modèle (solution de (@mtinberg).
Le programme d'extension de modèle naïf complet :
#!/bin/sh
PROG=$(basename $0)
usage()
{
echo "${PROG} <template-file> [ <config-file> ]"
}
expand()
{
local template="$(cat $1)"
eval "echo \"${template}\""
}
case $# in
1) expand "$1";;
2) . "$2"; expand "$1";;
*) usage; exit 0;;
esac
Cela affichera l'extension sur la sortie standard ; redirigez simplement la sortie standard vers un fichier ou modifiez ce qui précède de manière évidente pour produire le fichier de sortie souhaité.
Mises en garde : L'expansion du fichier de modèle ne fonctionnerait pas si le fichier contenait des guillemets doubles sans échappement ("
). Pour des raisons de sécurité, nous devrions probablement inclure des vérifications d'intégrité évidentes ou, mieux encore, effectuer une transformation d'échappement du shell si le fichier de modèle est généré par une entité externe.
Solution 4 :
Si vous voulez des modèles légers et réels plutôt que du code shell qui génère de nouveaux fichiers, les choix habituels sont sed
&awk
ou perl
. Voici un lien :http://savvyadmin.com/generate-text-from-templates-scripts-and-csv-data/
Moi, j'utiliserais un vrai langage comme perl, tcl, python, ruby ou autre chose dans cette classe. Quelque chose construit pour les scripts. Ils ont tous de bons outils de création de modèles simples et des tonnes d'exemples dans Google.
Solution 5 :
J'utilise shtpl pour cela. (Projet personnel, ce qui signifie qu'il n'est pas largement utilisé. Mais peut-être que vous voulez quand même le tester)
Par exemple, vous voulez générer un /etc/network/interfaces à partir d'un fichier csv, vous pouvez le faire comme ça :
Contenu du fichier CSV (ici test.csv) :
eth0;10.1.0.10;255.255.0.0;10.1.0.1
eth1;192.168.0.10; 255.255.255.0;192.168.0.1
Modèle (ici interfaces.tpl) :
#% IFS=';'
#% while read "Val1" "Val2" "Val3" "Val4"; do
auto $Val1
iface $Val1 inet static
address $Val2
netmask $Val3
gateway $Val4
#% done < "$CSVFILE"
Commande :
$ CSVFILE=test.csv sh -c "$( shtpl interfaces.tpl )"
Résultat :
auto eth0
iface eth0 inet static
address 10.1.0.10
netmask 255.255.0.0
gateway 10.1.0.1
auto eth1
iface eth1 inet static
address 192.168.0.10
netmask 255.255.255.0
gateway 192.168.0.1
Amusez-vous !