126 votes

Comment substituer des variables shell dans des fichiers texte complexes

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 enregistrer dans de nouveaux fichiers où toutes les variables auraient été remplacées.

Pour ce faire, j'ai utilisé le shell script suivant (trouvé 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 syntaxique des fichiers XML donne lieu à des tonnes d'erreurs

Y a-t-il une meilleure façon de le faire ? (dans le shell script... Je sais que cela se fait facilement avec Ant par exemple)

Bien à vous

278voto

derobert Points 26258

En cherchant, il s'avère que sur mon système, il y a une envsubst qui fait partie du paquet gettext-base.

Donc, cela rend les choses plus faciles :

envsubst < "source.txt" > "destination.txt"

Notez que si vous voulez utiliser le même fichier pour les deux, vous devrez utiliser quelque chose comme le programme moreutil's sponge comme suggéré par Johnny Utahh : envsubst < "source.txt" | sponge "source.txt" . (Parce que la redirection du shell va sinon vider le fichier avant sa lecture).

84voto

Michael Points 901

En référence à la réponse 2, lors de la discussion sur envsubst, vous avez demandé :

Comment puis-je le faire fonctionner avec les variables qui sont déclarées dans mon .sh script ?

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 en utilisant l'option envsubst SHELL_FORMAT (ce qui évite le remplacement involontaire d'une chaîne de caractères dans l'entrée par une valeur de variable shell commune - par ex. $HOME ).

Par exemple :

export VAR1='somevalue' VAR2='someothervalue'
MYVARS='$VAR1:$VAR2'

envsubst "$MYVARS" <source.txt >destination.txt

Remplacera toutes les instances de $VAR1 y $VAR2 (et seulement VAR1 y VAR2 ) en source.txt con 'somevalue' y 'someothervalue' respectivement.

24voto

inetphantom Points 31

Je sais que ce sujet est ancien, mais j'ai une solution plus simple qui fonctionne sans exporter les variables. Il peut s'agir d'une seule ligne, mais je préfère la diviser en utilisant la fonction \ en fin de 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 à la même ligne que envsubst est à considérer comme des variables d'environnement.

Le site '$var1,$var3' est facultatif pour ne remplacer que ceux qui sont spécifiés. Imaginons un fichier d'entrée contenant ${VARIABLE_USED_BY_JENKINS} qui ne doit pas être remplacé.

12voto

Dado Points 449
  1. Définissez votre variable ENV

    $ export MY_ENV_VAR=congratulation

  2. Créer un fichier modèle ( dans.txt ) avec le contenu suivant

    $MY_ENV_VAR

Vous pouvez également utiliser toutes les autres variables ENV définies par votre système comme (sous linux) $TERM, $SHELL, $HOME...

  1. Exécutez cette commande pour rapatrier toutes les variables d'environnement dans votre système d'exploitation. dans.txt et d'écrire le résultat dans le fichier out.txt

    $ envsubst "printf '${%s} ' $(sh -c "env|cut -d'=' -f1")" < in.txt > out.txt

  2. Vérifier le contenu du fichier out.txt

    $ cat out.txt

et vous devriez voir "félicitations".

5voto

Arik Points 611

Si vous voulez que les variables env soient remplacées dans vos fichiers sources tout en gardant toutes les variables non env telles quelles, vous pouvez utiliser la commande suivante :

envsubst "$(printf '${%s} ' $(env | sed 's/=.*//'))" < source.txt > destination.txt

La syntaxe pour remplacer uniquement des variables spécifiques est expliqué ici . La commande ci-dessus utilise un sous-shell pour dresser la liste de toutes les variables définies, puis la transmet à la commande envsubst

Donc s'il y a une variable env définie appelée $NAME et votre source.txt ressemble à ceci :

Hello $NAME
Your balance is 123 ($USD)

Le site destination.txt le sera :

Hello Arik
Your balance is 123 ($USD)

Notez que le $NAME est remplacé et le $USD n'est pas touchée

Prograide.com

Prograide est une communauté de développeurs qui cherche à élargir la connaissance de la programmation au-delà de l'anglais.
Pour cela nous avons les plus grands doutes résolus en français et vous pouvez aussi poser vos propres questions ou résoudre celles des autres.

Powered by:

X