ファイル内の環境変数を置換/評価する簡単な方法はありますか?たとえば、次のようなファイルconfig.xml
があるとします。
<property>
<name>instanceId</name>
<value>$INSTANCE_ID</value>
</property>
<property>
<name>rootPath</name>
<value>/services/$SERVICE_NAME</value>
</property>
...等。ファイル内の$INSTANCE_ID
をINSTANCE_ID
環境変数の値で置き換え、$SERVICE_NAME
をSERVICE_NAME
env変数の値で置き換えます。必要な環境変数が事前にわからない(または、誰かが新しい環境変数を構成ファイルに追加した場合にスクリプトを更新する必要がない)。ありがとう!
envsubst
(gnu gettext
の一部)を使用できます。
envsubst < infile
ファイル内の環境変数を対応する値に置き換えます。 変数名は、英数字またはアンダースコアのみで構成する必要がありますASCII文字で、数字で開始することはできません。それ以外の場合、このような変数参照は無視されます。
特定の環境変数のみを置き換えるには、 この質問を参照してください。
これはあまり良くありませんが、うまくいきます
( echo "cat <<EOF" ; cat config.xml ; echo EOF ) | sh
シェルスクリプト内にある場合は、次のようになります。
#! /bin/sh
cat <<EOF
<property>
<name>instanceId</name>
<value>$INSTANCE_ID</value>
</property>
EOF
編集、2番目の提案:
eval "echo \"$(cat config.xml)\""
厳密には質問に関係していませんが、変数がファイルから読み取られた場合は編集します。
(. .env && eval "echo \"$(cat config.xml)\"")
Perl(gettextとenvsubst
は除く)を使用している場合は、短いスクリプトで簡単に置き換えることができます。
$ 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>
変数名には大文字とアンダースコアしか使用できないと思いましたが、最初のパターンは必要に応じて簡単に変更できます。 $ENV{...}
は、Perlが見る環境を参照します。
${...}
構文をサポートする場合、または未設定の変数でエラーをスローする場合は、さらに作業が必要になります。 gettext
のenvsubst
に相当するものは次のとおりです。
Perl -pe 's/\$(\{)?([a-zA-Z_]\w*)(?(1)\})/$ENV{$2}/g'
プロセス環境を介してそのような変数を供給することは一般的に少し不審に思われると思いますが:ファイルで任意の変数を使用することはできません(それらには特別な意味がある可能性があるため)、値のいくつかはおそらく少なくとも半それらの機密データ。
このために自分のスクリプトを提案してもいいですか?
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
cmake
のconfigure_file
関数を使用します。
<input>
ファイルを<output>
ファイルにコピーし、入力ファイルのコンテンツで@VAR@
または${VAR}
として参照される変数値を置き換えます。各変数参照は、変数の現在の値、または変数が定義されていない場合は空の文字列に置き換えられます。
Perlの回答と同様に、環境変数の置換はPHP CLIに委任できます。PHPへの依存関係は、使用する。
php -r 'echo preg_replace_callback("/\\$([a-z0-9_]+)/i", function ($matches) { return getenv($matches[1]); }, fread(STDIN, 8192));' < input.file > output.file
さらに進んで、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')
);
使用法は次のとおりです。
envsubst < input.file > output.file