如何为命令动态设置环境变量?

use*_*913 6 bash environment-variables associative-array template

我想使用某种带有纯 bash 的简约模板引擎并且envsubst

\n
user@host:~$ env -i FOO=foo BAR="bar baz" envsubst \'$FOO,$BAR\' \\\n  <<< \'Hello "$FOO" and "$BAR"!\'\nHello "foo" and "bar baz"!\n
Run Code Online (Sandbox Code Playgroud)\n

以上有效,但仅包含静态变量。

\n

现在让我们假设环境变量是动态给出的,就像关联数组一样:

\n
declare -A MY_ENV=([FOO]=foo [BAR]="bar baz")\n
Run Code Online (Sandbox Code Playgroud)\n

解析数组键值对仅适用于没有空格的环境值(错误):

\n
env -i \\\n  $(for k in "${!MY_ENV[@]}"; do printf "%s=%s " $k "${MY_ENV[$k]}"; done) \\ \n  envsubst #...\n
Run Code Online (Sandbox Code Playgroud)\n

尝试用引号(用 note \'%s\' 代替%s )括起环境值也会出错:

\n
env -i \\\n  $(for k in "${!MY_ENV[@]}"; do printf "%s=\'%s\' " $k "${MY_ENV[$k]}"; done) \\ \n  envsubst #...\n
Run Code Online (Sandbox Code Playgroud)\n

输出set -x:\n原因:set -x表明 的参数env变成了一个巨大的字符串

\n
+ env -i \'FOO=\'\\\'\'foo\'\\\'\'\' \'BAR=\'\\\'\'bar\' \'baz\'\\\'\'\' envsubst #...\nenv: \xe2\x80\x98baz\'\xe2\x80\x99: No such file or directory\n
Run Code Online (Sandbox Code Playgroud)\n

我肯定错过了逃生课(再次……)。我如何重写最后一个示例才能正常工作?

\n

gle*_*man 4

这是[BashFAQ/050] —— 你必须使用一个数组来确保每一"key=value"对都被正确引用。

vars=()
for k in "${!MY_ENV[@]}"; do
    vars+=( "$k=${MY_ENV[$k]}" )
done
env -i "${vars[@]}" envsubst '$FOO,$BAR' <<< 'Hello "$FOO" and "$BAR"!'
Run Code Online (Sandbox Code Playgroud)
Hello "foo" and "bar baz"!
Run Code Online (Sandbox Code Playgroud)

请注意,我没有注入任何额外的引号字符。


扩展到这样我们就不必对变量名称进行硬编码:

keys=( "${!MY_ENV[@]}" )
printf -v varnames ',%s' "${keys[@]/#/'$'}"

env -i "${vars[@]}" envsubst "${varnames#,}" <<< 'Hello "$FOO" and "$BAR"!'

# or without the `varnames` temp var
env -i "${vars[@]}" envsubst "$(IFS=,; echo "${keys[*]/#/'$'}")" <<< 'Hello "$FOO" and "$BAR"!'
Run Code Online (Sandbox Code Playgroud)