bash envsubst:未设置变量的默认值

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/50230361/
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

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-09-18 16:54:50  来源:igfitidea点击:

envsubst: default values for unset variables

linuxbashenvironment-variables

提问by chrx

I've got a json file input.jsonlike the following one:

我有一个input.json像下面这样的json 文件:

{
  "variable" : "${ENV_VAR}"
}

of course, I can invoke envsubst from bash like the following:

当然,我可以像下面这样从 bash 调用 envsubst:

$ export ENV_VAR=myvalue
$ envsubst < input.json > output.json
$ cat output.json
{
  "variable" : "myvalue"
}

Now, I wish I could set default values for variables in the input.json for the case when ENV_VARis not set, like in the following example which, as unfortunately can be seen in the example below, doesn't work:

现在,我希望我可以为 input.json 中的变量设置默认值,用于ENV_VAR未设置的情况,如下例所示,不幸的是,在下面的示例中可以看到,它不起作用:

$ cat input.json
{
  "variable" : "${ENV_VAR:=defaultvalue}"
}
$ export ENV_VAR=newvalue
$ envsubst < input.json > output.json
$ cat output.json
{
  "variable" : "${ENV_VAR:=defaultvalue}"
}
$ unset ENV_VAR
$ envsubst < input.json > output.json
$ cat output.json
{
  "variable" : "${ENV_VAR:=defaultvalue}"
}

What's curious, if I execute the envsubst like in the following example (without involving an input file), it works

奇怪的是,如果我像下面的例子一样执行 envsubst(不涉及输入文件),它就可以工作

$ export ENV_VAR=myvalue
$ echo "value is ${ENV_VAR:=defaultvalue}" | envsubst
value is myvalue
$ unset ENV_VAR
$ echo "value is ${ENV_VAR:=defaultvalue}" | envsubst
value is defaultvalue

Where is the problem with the files?

文件问题出在哪里?

回答by Robin479

According to man envsubst, envsubstwill only ever replace references to environment variables in the form of ${VAR}or $VAR. Special shell features like ${VAR:-default}are not supported. The only thing you could do is to (re)define all variables in the environment of the envsubstinvocation and assign local default values, if they are missing:

根据man envsubst,envsubst只会以${VAR}或的形式替换对环境变量的引用$VAR${VAR:-default}不支持特殊的外壳功能,如。您唯一能做的就是(重新)定义envsubst调用环境中的所有变量并分配本地默认值(如果它们丢失):

ENV_VAR="${ENV_VAR:-defaultvalue}" \
OTHER_VAR="${OTHER_VAR:-otherdefault}" \
envsubst < input.json > output.json

Note, that this is actually a single command line split into multiple lines each ending with a line continuation \. The first two lines are variable assignments, that are only effective in the environment of the executed command envsubstrin the last line. What's happening is, that the shell will create an environment for the execution of the command (as it would always do). That environment is initially a copy of the current shell environment. Within that new environment ENV_VARand OTHER_VARare assigned the values of expanding the expression ${VAR:-default}, which essentially expands to defaultunless VARis defined and has a none-empty value. The command envsubstis executed, receiving the file input.jsonas standard-input and having its standard-output redirected to output.json(both is done by the shell). After the command execution, the shell deletes the command environment returning to its original environment, i.e. the local variable assignments are no longer effective.

请注意,这实际上是将单个命令行拆分为多行,每行以换行符结尾\。前两行是变量赋值,只envsubstr在最后一行执行命令的环境中有效。正在发生的事情是,shell 将为命令的执行创建一个环境(就像往常一样)。该环境最初是当前 shell 环境的副本。在那个新环境中ENV_VAROTHER_VAR并被分配扩展表达式的值${VAR:-default},它本质上扩展为default除非VAR被定义并且具有非空值。envsubst执行命令,接收文件input.json作为标准输入并将其标准输出重定向到output.json(两者都是由外壳完成的)。命令执行后,shell 删除命令环境,返回原来的环境,即局部变量赋值不再有效。

There is no way to define default values from inside the JSON file, unless you implement a program to do so yourself, or use another tool that can to that.

没有办法从 JSON 文件内部定义默认值,除非您自己实现一个程序来这样做,或者使用另一个可以做到这一点的工具。

You could do something like the following, but it is NOT RECOMMENDED:

您可以执行以下操作,但不推荐

eval echo "$(cat input.json)" > output.json

which will read input.jsoninto a string, and than evaluate the command echo <string>as if it was type literally, which means that any embedded ${VAR:-default}stuff should be expanded by the shell before the string is passed to echo. BUTany other embedded shell feature will be evaluated as well, which poses a HUGE SECURITY RISK.

这将读input.json入一个字符串,然后eval将命令echo <string>视为字面上的类型,这意味着${VAR:-default}在将字符串传递给echo. 但是任何其他嵌入式外壳功能也将被评估,这会带来巨大的安全风险

回答by mash

I'm using https://github.com/a8m/envsubstand it has enhancements over the original gettext envsubst that the expressions in the template file supports default values.

我正在使用https://github.com/a8m/envsubst并且它对原始 gettext envsubst 进行了增强,即模板文件中的表达式支持默认值。

The example in the README just works.

README 中的示例有效。

echo 'welcome $HOME ${USER:=a8m}' | envsubst