[英]Replace placeholders with corresponding env variables
I have a configuration file with placeholders like this (stored in /tmp/var
for this example)我有一个带有像这样的占位符的配置文件(本示例存储在
/tmp/var
中)
ldap_bind_dn='${bind_dn}'
Now I'd like replace ${bind_dn}
with the the environment variable of the same name (which is set inside Docker).现在我想将
${bind_dn}
替换为同名的环境变量(在 Docker 中设置)。
export $bind_dn=CN=my-user,CN=Users,DC=example,DC=com
The expected result after processing aboves test file would be处理上述测试文件后的预期结果将是
ldap_bind_dn='CN=my-user,CN=Users,DC=example,DC=com'
I tried sed
but it doesn't replace it to the value of the env variable我试过
sed
但它没有将它替换为 env 变量的值
$ sed "s#\${\(.*\)}#$\1#" /tmp/var
bind_dn='$bind_dn'
Why sed
replace with $bind_dn
instead of the value?为什么
sed
替换为$bind_dn
而不是值? I'd expect that the variable is processed because I haven't escaped the $
sign.我希望变量被处理,因为我没有转义
$
符号。
The expression itself works, only the substitution doesn't:表达式本身有效,只有替换无效:
$ sed "s#\${\(.*\)}#test123#" /tmp/var
bind_dn='test123'
The replacement is also done correctly when the target variable is hardcoded当目标变量被硬编码时,替换也正确完成
$ sed "s#\${\(.*\)}#$bind_dn#" /tmp/var
bind_dn='CN=my-user,CN=Users,DC=example,DC=com'
But since we have a bunch of configuration variables, I'd like to automatically replace all env variables in the format ${NAME}
automatically.但由于我们有一堆配置变量,我想自动替换所有格式
${NAME}
的环境变量。
Not the most elegant solution, but this one works in bash:不是最优雅的解决方案,但这个适用于 bash:
sed 's#\${\(.*\)}#`{echo,"$\1"}`#' /tmp/var | xargs -n1 -I{} echo echo "{}" | bash -s
It is a little bit tricky because you need bash execution for the variable replacement, that's why I'm piping it to bash -s
这有点棘手,因为您需要执行 bash 来执行变量替换,这就是为什么我将它传递给
bash -s
While the env variable could be parsed by executing eval
with mapfile
, this seems not suiteable for me because its a ini configuration file.虽然可以通过使用
mapfile
执行eval
来解析 env 变量,但这似乎不适合我,因为它是一个 ini 配置文件。 The sections marked with brackets like [general]
would throw errors.标有
[general]
等括号的部分会引发错误。 And I also have concerns to just execute the WHOLE line, which allows executing any command.而且我还担心只执行允许执行任何命令的整行。
This is fixed by the following awk
:这是由以下
awk
的:
awk '{while(match($0,"[$]{[^}]*}")) {var=substr($0,RSTART+2,RLENGTH -3);gsub("[$]{"var"}",ENVIRON[var])}}1' < /tmp/var > /tmp/var
Why sed replace with $bind_dn instead of the value?
为什么 sed 替换为 $bind_dn 而不是值?
Because sed is not supposed to do shell parameter expansion in its pattern space.因为sed不应该在其模式空间中进行 shell 参数扩展。 That's the job of the shell mainly.
这主要是 shell 的工作。
Using GNU sed :使用 GNU sed :
~> cat /tmp/var
ldap_bind_dn='${bind_dn}'
~> export bind_dn=CN=my-user,CN=Users,DC=example,DC=com
~> sed -E 's/^\w+=.*/echo "&"/e' /tmp/var
ldap_bind_dn='CN=my-user,CN=Users,DC=example,DC=com'
The e
command (a GNU extension) in e
命令(GNU 扩展)
sed -E 's/^\w+=.*/echo "&"/e'
executes the command that is found in pattern space and replaces the pattern space with the output.执行在模式空间中找到的命令并将模式空间替换为 output。 For this example, pattern space is
ldap_bind_dn='${bind_dn}'
, and is replaced with the output of echo "ldap_bind_dn='${bind_dn}'"
( &
references the whole matched portion of the pattern space in echo "&"
).对于此示例,模式空间是
ldap_bind_dn='${bind_dn}'
,并替换为echo "ldap_bind_dn='${bind_dn}'"
( &
引用echo "&"
中的模式空间的整个匹配部分)。 Since the argument of echo
is in double quotes, it is subject to parameter expansion when it is executed by the shell.由于
echo
的参数是双引号,所以在shell执行时会受到参数扩展的影响。
Caveat : Make sure that the file (/tmp/var in this example) comes from a trusted source.警告:确保文件(本例中为 /tmp/var)来自受信任的来源。 Otherwise it may contain lines like
foo='$(some_nasty_command)'
, which is executed when the sed command above runs.否则它可能包含像
foo='$(some_nasty_command)'
这样的行,当上面的sed命令运行时执行。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.