Existe-t-il un moyen simple de remplacer/évaluer les variables d'environnement dans un fichier? Comme disons que j'ai un fichier config.xml
cela contient:
<property>
<name>instanceId</name>
<value>$INSTANCE_ID</value>
</property>
<property>
<name>rootPath</name>
<value>/services/$SERVICE_NAME</value>
</property>
...etc. Je veux remplacer $INSTANCE_ID
dans le fichier avec la valeur de INSTANCE_ID
variable d'environnement, $SERVICE_NAME
avec la valeur de SERVICE_NAME
env var. Je ne saurai pas a priori quelles variables d'environnement sont nécessaires (ou plutôt, je ne veux pas avoir à mettre à jour le script si quelqu'un ajoute une nouvelle variable d'environnement au fichier de configuration). Merci!
Vous pouvez utiliser envsubst
(partie de gnu gettext
):
envsubst < infile
remplacera les variables d'environnement de votre fichier par leur valeur correspondante. Les noms de variables doivent être constitués uniquement de caractères alphanumériques ou de soulignement ASCII caractères, ne commencez pas par un chiffre et ne soyez pas vide; sinon, une telle référence de variable est ignoré.
Pour remplacer uniquement certaines variables d'environnement, voir cette question.
Ce n'est pas très sympa mais ça marche
( echo "cat <<EOF" ; cat config.xml ; echo EOF ) | sh
Si c'était dans un script Shell, cela ressemblerait à:
#! /bin/sh
cat <<EOF
<property>
<name>instanceId</name>
<value>$INSTANCE_ID</value>
</property>
EOF
Edit, deuxième proposition:
eval "echo \"$(cat config.xml)\""
Modifier, pas strictement lié à la question, mais en cas de variables lues à partir du fichier:
(. .env && eval "echo \"$(cat config.xml)\"")
S'il vous arrive d'avoir Perl (mais pas gettext et envsubst
), vous pouvez faire le remplacement simple avec un court script:
$ export INSTANCE_ID=foo; export SERVICE_NAME=bar;
$ Perl -pe 's/\$([_A-Z]+)/$ENV{$1}/g' < config.xml
<property>
<name>instanceId</name>
<value>foo</value>
</property>
<property>
<name>rootPath</name>
<value>/services/bar</value>
</property>
J'ai supposé que les noms de variables n'auront que des lettres majuscules et des traits de soulignement, mais le premier modèle devrait être facile à modifier selon les besoins. $ENV{...}
fait référence à l'environnement que Perl voit.
Si vous souhaitez prendre en charge le ${...}
syntaxe ou lancer une erreur sur les variables non définies, vous aurez besoin de plus de travail. Un équivalent proche de gettext
envsubst
serait:
Perl -pe 's/\$(\{)?([a-zA-Z_]\w*)(?(1)\})/$ENV{$2}/g'
Bien que je pense que l'alimentation de variables comme celle-ci via l'environnement de processus semble un peu aléatoire en général: vous ne pouvez pas utiliser de variables arbitraires dans les fichiers (car elles peuvent avoir des significations spéciales), et certaines des valeurs peuvent éventuellement avoir au moins des données sensibles en eux.
Puis-je suggérer mon propre script pour cela?
https://github.com/rydnr/set-square/blob/master/.templates/common-files/process-file.sh
#!/bin/bash /usr/local/bin/dry-wit
# Copyright 2016-today Automated Computing Machinery S.L.
# Distributed under the terms of the GNU General Public License v3
function usage() {
cat <<EOF
$SCRIPT_NAME -o|--output output input
$SCRIPT_NAME [-h|--help]
(c) 2016-today Automated Computing Machinery S.L.
Distributed under the terms of the GNU General Public License v3
Processes a file, replacing any placeholders with the contents of the
environment variables, and stores the result in the specified output file.
Where:
* input: the input file.
* output: the output file.
Common flags:
* -h | --help: Display this message.
* -v: Increase the verbosity.
* -vv: Increase the verbosity further.
* -q | --quiet: Be silent.
EOF
}
# Requirements
function checkRequirements() {
checkReq envsubst ENVSUBST_NOT_INSTALLED;
}
# Error messages
function defineErrors() {
export INVALID_OPTION="Unrecognized option";
export ENVSUBST_NOT_INSTALLED="envsubst is not installed";
export NO_INPUT_FILE_SPECIFIED="The input file is mandatory";
export NO_OUTPUT_FILE_SPECIFIED="The output file is mandatory";
ERROR_MESSAGES=(\
INVALID_OPTION \
ENVSUBST_NOT_INSTALLED \
NO_INPUT_FILE_SPECIFIED \
NO_OUTPUT_FILE_SPECIFIED \
);
export ERROR_MESSAGES;
}
## Parses the input
## dry-wit hook
function parseInput() {
local _flags=$(extractFlags $@);
local _flagCount;
local _currentCount;
# Flags
for _flag in ${_flags}; do
_flagCount=$((_flagCount+1));
case ${_flag} in
-h | --help | -v | -vv | -q)
shift;
;;
-o | --output)
shift;
OUTPUT_FILE="${1}";
shift;
;;
esac
done
# Parameters
if [[ -z ${INPUT_FILE} ]]; then
INPUT_FILE="$1";
shift;
fi
}
## Checking input
## dry-wit hook
function checkInput() {
local _flags=$(extractFlags $@);
local _flagCount;
local _currentCount;
logDebug -n "Checking input";
# Flags
for _flag in ${_flags}; do
_flagCount=$((_flagCount+1));
case ${_flag} in
-h | --help | -v | -vv | -q | --quiet)
;;
-o | --output)
;;
*) logDebugResult FAILURE "fail";
exitWithErrorCode INVALID_OPTION ${_flag};
;;
esac
done
if [[ -z ${INPUT_FILE} ]]; then
logDebugResult FAILURE "fail";
exitWithErrorCode NO_INPUT_FILE_SPECIFIED;
fi
if [[ -z ${OUTPUT_FILE} ]]; then
logDebugResult FAILURE "fail";
exitWithErrorCode NO_OUTPUT_FILE_SPECIFIED;
fi
}
## Replaces any placeholders in given file.
## -> 1: The file to process.
## -> 2: The output file.
## <- 0 if the file is processed, 1 otherwise.
## <- RESULT: the path of the processed file.
function replace_placeholders() {
local _file="${1}";
local _output="${2}";
local _rescode;
local _env="$(IFS=" \t" env | awk -F'=' '{printf("%s=\"%s\" ", $1, $2);}')";
local _envsubstDecl=$(echo -n "'"; IFS=" \t" env | cut -d'=' -f 1 | awk '{printf("${%s} ", $0);}'; echo -n "'";);
echo "${_env} envsubst ${_envsubstDecl} < ${_file} > ${_output}" | sh;
_rescode=$?;
export RESULT="${_output}";
return ${_rescode};
}
## Main logic
## dry-wit hook
function main() {
replace_placeholders "${INPUT_FILE}" "${OUTPUT_FILE}";
}
# vim: syntax=sh ts=2 sw=2 sts=4 sr noet
Utilisez cmake
configure_file
une fonction.
Il copie un <input>
fichier vers un <output>
fichier et substitue les valeurs des variables référencées comme @VAR@
ou ${VAR}
dans le contenu du fichier d'entrée. Chaque référence de variable sera remplacée par la valeur actuelle de la variable ou la chaîne vide si la variable n'est pas définie.
De la même manière que pour la réponse Perl, la substitution de variable d'environnement peut être déléguée à la PHP CLI. Dépendance de PHP peut être acceptable ou non selon la pile technologique dans utilisation.
php -r 'echo preg_replace_callback("/\\$([a-z0-9_]+)/i", function ($matches) { return getenv($matches[1]); }, fread(STDIN, 8192));' < input.file > output.file
Vous pouvez aller plus loin et le mettre dans un script réutilisable, par exemple, envsubst
:
#!/usr/bin/env php
<?php
echo preg_replace_callback(
'/\$(?<name>[a-z0-9_]+)/i',
function ($matches) {
return getenv($matches['name']);
},
file_get_contents('php://stdin')
);
L'usage serait:
envsubst < input.file > output.file