파일에서 환경 변수를 대체 / 평가하는 쉬운 방법이 있습니까? 다음과 같은 파일 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 var 값 으로 바꾸고 싶습니다 . 어떤 환경 변수가 필요한지 미리 알지 못합니다 (또는 누군가가 환경 파일에 새 환경 변수를 추가하는 경우 스크립트를 업데이트하고 싶지는 않습니다). 감사!
답변
당신은 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
두 번째 제안 수정 :
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
s ‘이 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
답변
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