Linux 替换属性文件中的环境变量
在Linux中,假设我有以下文件(例如conf.properties): 我想创建另一个替换了所有环境变量的文件…例如。假设环境变量$HOSTNAME为'myhost',且未设置$unconfigured,则脚本应生成以下输出:Linux 替换属性文件中的环境变量,linux,Linux,在Linux中,假设我有以下文件(例如conf.properties): 我想创建另一个替换了所有环境变量的文件…例如。假设环境变量$HOSTNAME为'myhost',且未设置$unconfigured,则脚本应生成以下输出: HOST_URL=http://myhost STD_CONFIG=http://myhost/config USER_CONFIG=http://myhost/config/ 我原以为这可以用简单的一行代码和某种sed/awk魔术来完成,但我不是专家,我的搜索一直在
HOST_URL=http://myhost
STD_CONFIG=http://myhost/config
USER_CONFIG=http://myhost/config/
我原以为这可以用简单的一行代码和某种sed/awk魔术来完成,但我不是专家,我的搜索一直在进行中,所以感谢您的帮助
编辑:
我应该提到,该文件实际上可以是任何格式的文本文件,例如xml。我只想用环境中当前设置的内容替换任何看起来像env变量的内容。我会这样做:
# 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
更新:
根据您问题中的更新,这不是一个好的解决方案
更新2:
这是基于一个假设。我已经尝试过(我不熟悉perl)删除未定义的变量
perl -p -e 's/\$\{([^}]+)\}/defined $ENV{$1} ? $ENV{$1} : $&/eg; s/\$\{([^}]+)\}//eg' yourfile.txt
应该适用于任何输入文本文件,但是您需要使用简化字符串匹配的${…}
格式定义变量
(关于eval邪恶的咆哮移到了a,以免混淆读者)多亏了@DarkDust,我想出了这个:
cat somefile | while read line; do echo $(eval echo `echo $line`); done > somefile.replaced
“eval是邪恶的”
这不是一个答案,而是一个警告。你真的不想那样做
附件1:恶意模板文件:
HOST_URL=http://$HOSTNAME
STD_CONFIG=http://$HOSTNAME/config
USER_CONFIG=http://$HOSTNAME/config/$unconfigured
&& cat /etc/redhat-release
[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)
毫无戒心的用户:
HOST_URL=http://$HOSTNAME
STD_CONFIG=http://$HOSTNAME/config
USER_CONFIG=http://$HOSTNAME/config/$unconfigured
&& cat /etc/redhat-release
[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)
注意最后一行强>
现在,想象一下可能的情况……我使用此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
我敢肯定,有人可以用
awk
…感受挑战!;)在三分之一的长度内完成这项工作 这里有一个简短的单行程序,它使用python的大括号格式来安全地完成这项任务:
contents=\"\"\"`cat $file`\"\"\"; python -c "import os;print $contents.format(**os.environ)"
- 避邪
- 允许输出花括号:使用
而不是{{
{
- 调用脚本时无需显式指定变量
设置.properties
:
# my properties file
someVar = {MY_ENV_VAR}
curlyBraceVar = has {{curly braces}}
然后,用以下方法进行替换:
$ 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}
这里有一个脚本:这就是
envsubst
的作用
echo 'Hello $USER'
Hello $USER
echo 'Hello $USER' | envsubst
Hello malvineous
不过,您可能会更像这样使用它:
envsubst < input.txt > output.txt
envsubtoutput.txt
envsubst
似乎是GNU gettext的一部分。下面是一段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`);
});
希望这对其他人有所帮助。如果您安装了nodejs,则可以运行
npx@utft/tt-e FOO=bar/path/to/input/path/to/output
或者您可以通过编程方式运行它
我不能假设该文件是有效的shell脚本(仅名称=值)-它可能是任何格式,例如xml。@Andy Whitfield:太糟糕了:-)然后您就转到awk/sed。您的编辑给了我一个想法:这个小金块:
在读取行时cat somefile;do echo$(eval echo
echo$line);done
此处的注释格式不太好,因此我将粘贴它作为参考答案。或更具可读性(IMHO):sed-e's/$HOSTNAME/myhost/'-e's/$unconfigured/
…假设我知道配置文件中使用的env变量,我可以使用这种技术,但我确实需要更通用的方法。@Shawn Chin谢谢!我可能会使用它,因为我喜欢${
使用属性的风格。我认为perl命令可以简化为perl-p-e的/\$\{([^}]+)\}/defined$ENV{$1}?$ENV{$1}:“/eg”yourfile.txt
,根据对相关问题的评论,而不是使用第二个正则表达式来删除空变量。您只需将$&
替换为”
@JoelPearson的正则表达式具有不删除反斜杠甚至一行的优点;-)现在看来这是一个解决方案,只要您知道您的输入文件除了变量之外将不会有$
。请不要使用它。请原谅提高声音,但这是一种需要尖叫的情况。请参阅我的ans中的解释wer.@Shawn没问题-谢谢你的警告。我使用perl行-效果很好。我更担心将来可能遇到的毫无戒心的用户。将警告作为一个单独的项目发布,以免引起混淆。这将省略行开头的空格以及包含#
的行。这让我想起了t哦。我很惊讶人们会这么认为。bash中应该有一个替换机制,真的!否则,我们应该为此编写一个标准工具。这并不能避免邪恶的评估,它只是混淆了它。echo';print“任意代码执行”;““>~/myfile;
创建一个文件,该文件会导致对一些任意代码进行求值。这似乎是这里唯一真正正确的答案。应该标记得更高。我只想对这个答案表示感谢。我和我的朋友正在与sed、awk和其他“技巧”作斗争这个答案拯救了我们。知识就是力量。谢谢!你应该考虑接受正确的答案。
// 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`);
});