简体   繁体   English

用相应的环境变量替换占位符

[英]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.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM