J'ai plusieurs fichiers texte dans lesquels j'ai introduit des variables Shell ($ VAR1 ou $ VAR2 par exemple).
Je voudrais prendre ces fichiers (un par un) et les sauvegarder dans de nouveaux fichiers où toutes les variables auraient été remplacées.
Pour ce faire, j'ai utilisé le script Shell suivant (présent sur StackOverflow):
while read line
do
eval echo "$line" >> destination.txt
done < "source.txt"
Cela fonctionne très bien sur des fichiers très basiques.
Mais sur des fichiers plus complexes, la commande "eval" en fait trop:
Les lignes commençant par "#" sont ignorées
L'analyse des fichiers XML génère des tonnes d'erreurs
Y a-t-il une meilleure façon de le faire? (en script shell ... je sais que cela se fait facilement avec Ant par exemple)
Sincères amitiés
En regardant, il se trouve que sur mon système, il existe une commande envsubst
qui fait partie du paquet gettext-base.
Donc, cela facilite les choses:
envsubst < "source.txt" > "destination.txt"
En vous référant à la réponse 2, lors de la discussion sur envsubst, vous avez demandé "Comment puis-je le faire fonctionner avec les variables déclarées dans mon script .sh?"
La réponse est que vous devez simplement exporter vos variables avant d'appeler envsubst.
Vous pouvez également limiter les chaînes de variables que vous souhaitez remplacer dans l'entrée à l'aide de l'argument envsubst Shell_FORMAT (en évitant le remplacement involontaire d'une chaîne dans l'entrée par une valeur de variable Shell commune, par exemple $ HOME).
Par exemple:
export VAR1='somevalue' VAR2='someothervalue'
MYVARS='$VAR1:$VAR2'
envsubst "$MYVARS" <source.txt >destination.txt
Remplacera toutes les occurrences de $ VAR1 et $ VAR2 (et uniquement VAR1 et VAR2) dans source.txt par 'somevalue' et 'someothervalue' respectivement.
Je sais que ce sujet est ancien, mais j’ai une solution de travail plus simple sans exporter les variables. Peut-être un oneliner, mais je préfère diviser en utilisant \
à la fin de la ligne.
var1='myVar1'\
var2=2\
var3=${var1}\
envsubst '$var1,$var3' < "source.txt" > "destination.txt"
# ^^^^^^^^^^^ ^^^^^^^^^^ ^^^^^^^^^^^^^^^
# define which to replace input output
Les variables doivent être définies sur la même ligne que envsubst
afin d’être considérées comme des variables d’environnement.
Le '$var1,$var3'
est facultatif pour ne remplacer que ceux spécifiés. Imaginez un fichier d’entrée contenant ${VARIABLE_USED_BY_JENKINS}
qui ne devrait pas être remplacé.
$ export MY_ENV_VAR=congratulation
$MY_ENV_VAR
Vous pouvez également utiliser toutes les autres variables ENV définies par votre système comme (sous linux) $ TERM, $ Shell, $ HOME ...
$ envsubst "`printf '${%s} ' $(sh -c "env|cut -d'=' -f1")`" < in.txt > out.txt
$ cat out.txt
et vous devriez voir "félicitation".
envsubst
semble exactement comme quelque chose que je voulais utiliser, mais l'option -v
m'a un peu surpris.
Alors que envsubst < template.txt
fonctionnait bien, la même chose avec l'option -v
ne fonctionnait pas:
$ cat /etc/redhat-release
Red Hat Enterprise Linux Server release 7.1 (Maipo)
$ envsubst -V
envsubst (GNU gettext-runtime) 0.18.2
Copyright (C) 2003-2007 Free Software Foundation, Inc.
License GPLv3+: GNU GPL version 3 or later <http://gnu.org/licenses/gpl.html>
This is free software: you are free to change and redistribute it.
There is NO WARRANTY, to the extent permitted by law.
Written by Bruno Haible.
Comme je l'ai écrit, cela ne fonctionnait pas:
$ envsubst -v < template.txt
envsubst: missing arguments
$ cat template.txt | envsubst -v
envsubst: missing arguments
Je devais le faire pour que cela fonctionne:
TEXT=`cat template.txt`; envsubst -v "$TEXT"
Peut-être que ça aide quelqu'un.
Si vous voulez vraiment uniquement utiliser bash (et sed), alors je passerai en revue chacune de vos variables d'environnement (retournées par set
en mode posix) et créerai un groupe de -e 'regex'
pour celui-ci, terminé par un -e 's/\$[a-zA-Z_][a-zA-Z0-9_]*//g'
, puis passerai tout ça pour sed.
Perl ferait un travail plus agréable, cependant, vous avez accès aux vars d’environnement en tant que tableau et vous pouvez effectuer des remplacements exécutables de sorte que vous ne correspondiez qu’à une seule variable d’environnement.
En fait, vous devez changer votre read
en read -r
, ce qui le fera ignorer les barres obliques inverses.
En outre, vous devriez échapper les guillemets et les barres obliques inverses .
while read -r line; do
line="${line//\\/\\\\}"
line="${line//\"/\\\"}"
line="${line//\`/\\\`}"
eval echo "\"$line\""
done > destination.txt < source.txt
Encore une façon terrible de faire de l’expansion.