Linux 替换属性文件中的环境变量
声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow
原文地址: http://stackoverflow.com/questions/5274343/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me):
StackOverFlow
Replacing environment variables in a properties file
提问by Andy Whitfield
In Linux, say I have the following file (e.g. conf.properties):
在 Linux 中,假设我有以下文件(例如 conf.properties):
HOST_URL=http://$HOSTNAME
STD_CONFIG=http://$HOSTNAME/config
USER_CONFIG=http://$HOSTNAME/config/$unconfigured
I want to create another file with all the environment variables replaced...e.g. say the environment variable $HOSTNAME is 'myhost' and $unconfigured is not set, a script should produce the following output:
我想创建另一个替换了所有环境变量的文件......例如说环境变量 $HOSTNAME 是 'myhost' 并且 $unconfigured 没有设置,脚本应该产生以下输出:
HOST_URL=http://myhost
STD_CONFIG=http://myhost/config
USER_CONFIG=http://myhost/config/
I was thinking this could be done in a simple one-liner with some sort of sed/awk magic, but I'm no expert and my searches have been in vein, so appreciate any help.
我想这可以用某种 sed/awk 魔法在一个简单的单行中完成,但我不是专家,我的搜索一直在进行,所以感谢任何帮助。
Edit:
编辑:
I should mention that the file can really be any format text file, for example xml. I just want to replace anything that looks like an env variable with whatever is currently set in the environment.
我应该提到该文件实际上可以是任何格式的文本文件,例如 xml。我只想用环境中当前设置的任何内容替换任何看起来像 env 变量的内容。
采纳答案by Shawn Chin
sed 's/$HOSTNAME/myhost/g;s/$unconfigured//g' yourfile.txt > another_file.txt
update:
更新:
Based on updates in your question, this won't be a good solution.
根据您问题中的更新,这不是一个好的解决方案。
update2 :
更新2:
This is based on an answer to a related question. I've hacked at it (I'm unfamiliar with perl) to remove undefined vars.
这是基于对相关问题的回答。我已经破解了它(我不熟悉 perl)以删除未定义的变量。
perl -p -e 's/$\{([^}]+)\}/defined $ENV{} ? $ENV{} : $&/eg; s/$\{([^}]+)\}//eg' yourfile.txt
Should work for any input text file, however you will need to define vars using the ${...}
format which simplifies the string matching.
应该适用于任何输入文本文件,但是您需要使用${...}
简化字符串匹配的格式来定义变量。
(rant regarding the evilness of eval moved to a separate postso as not to confuse readers)
(关于 eval 邪恶的咆哮移到一个单独的帖子,以免混淆读者)
回答by DarkDust
I'd do it like this:
我会这样做:
# Set the $HOSTNAME and other variables
# Now evaluate the properties file as a shell script.
. config.properties
# Write the values
cat >somefile <<EOF
HOST_URL=$HOST_URL
STD_CONFIG=$STD_CONFIG
USER_CONFIG=$USER_CONFIG
EOF
Edit: Or this very nasty thing (I'm sure there's a better way)
编辑:或者这个非常讨厌的东西(我确定有更好的方法)
for name in HOST_URL STD_CONFIG USER_CONFIG
echo "$name=$(eval echo `echo '$'$name`)" >>somefile
end
回答by Andy Whitfield
Thanks to @DarkDust I came up with this:
感谢@DarkDust 我想出了这个:
cat somefile | while read line; do echo $(eval echo `echo $line`); done > somefile.replaced
回答by Shawn Chin
"eval is evil"
“评估是邪恶的”
This is not an answer, but a warning in response to using eval for this task. You really really reallydon't want to do that.
这不是答案,而是针对使用 eval 执行此任务的警告。你真的真的真的不想那样做。
Exhibit 1: a malicious template file:
图表 1:恶意模板文件:
HOST_URL=http://$HOSTNAME
STD_CONFIG=http://$HOSTNAME/config
USER_CONFIG=http://$HOSTNAME/config/$unconfigured
&& cat /etc/redhat-release
An unsuspecting user:
一个毫无戒心的用户:
[lsc@aphek]$ cat somefile | while read line; do echo $(eval echo `echo $line`); done
HOST_URL=http://xyz
STD_CONFIG=http://xyz/config
USER_CONFIG=http://xyz/config/
Red Hat Enterprise Linux WS release 4 (Nahant Update 9)
Note the last line!
注意最后一行!
Now, imagine the possibilities....
现在,想象一下可能性......
回答by Elias Probst
I used this oneliner to replace ${VARIABLE}
style variables in a file:
我使用这个 oneliner 替换${VARIABLE}
文件中的样式变量:
TARGET_FILE=/etc/apache2/apache2.conf; for VARNAME in $(grep -P -o -e '$\{\S+\}' ${TARGET_FILE} | sed -e 's|^${||g' -e 's|}$||g' | sort -u); do sed -i "s|${$(echo $VARNAME)}|${!VARNAME}|g" ${TARGET_FILE}; done
I'm pretty sure someone can do this in 1/3rd of the length using awk
… feel challenged! ;)
我很确定有人可以使用 1/3 的长度做到这一点awk
……感到有挑战!;)
回答by Aneil Mallavarapu
Here's a short one-liner that uses python's curly brace formatting to safely do the magic:
这是一个简短的单行代码,它使用 python 的花括号格式来安全地发挥作用:
contents=\"\"\"`cat $file`\"\"\"; python -c "import os;print $contents.format(**os.environ)"
- avoids evil eval
- allows outputting curly braces: use
{{
instead of{
- no need to specify vars explicitly when calling the script
- 避免邪恶的评估
- 允许输出花括号:使用
{{
代替{
- 调用脚本时无需显式指定变量
For example, given properties file settings.properties
:
例如,给定的属性文件settings.properties
:
# my properties file
someVar = {MY_ENV_VAR}
curlyBraceVar = has {{curly braces}}
Then, do the substitution with:
然后,使用以下方法进行替换:
$ export MY_ENV_VAR="hello"
$ file=settings.properties
$ contents=\"\"\"`cat $file`\"\"\"; python -c "import os;print $contents.format(**os.environ)"
# my properties file
someVar = hello
curlyBraceVar = has {curly braces}
A script is here: https://raw.githubusercontent.com/aneilbaboo/machome/master/bin/substenv
脚本在这里:https: //raw.githubusercontent.com/aneilbaboo/machome/master/bin/substenv
回答by Malvineous
This is what envsubst
is for.
这envsubst
就是为了。
echo 'Hello $USER'
Hello $USER
echo 'Hello $USER' | envsubst
Hello malvineous
You would probably use it more like this though:
不过,您可能会更像这样使用它:
envsubst < input.txt > output.txt
envsubst
seems to be part of GNU gettext.
envsubst
似乎是 GNU gettext 的一部分。
回答by Robert Massaioli
Here is a snippet of Javascript that I like to have around for solving this exact problem:
这是我喜欢用来解决这个确切问题的一段 Javascript 代码:
// A Javascript version of envsubst for our builds
// Purpose: replace all ocurrences of ${VAR} with the equivalent var from the environment from stdin
var readline = require('readline');
var rl = readline.createInterface({
input: process.stdin,
output: process.stdout,
terminal: false
});
const environment = process.env;
rl.on('line', function(line) {
const newLine = line.replace(/$\{([a-zA-Z0-9_]+)\}/g, function(_match, variable) {
const envVar = environment[variable];
return envVar ? envVar : '';
});
process.stdout.write(`${newLine}\n`);
});
Hopefully this helps somebody else.
希望这对其他人有帮助。