use*_*913 6 bash environment-variables associative-array template
我想使用某种带有纯 bash 的简约模板引擎并且envsubst
:
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现在让我们假设环境变量是动态给出的,就像关联数组一样:
\ndeclare -A MY_ENV=([FOO]=foo [BAR]="bar baz")\n
Run Code Online (Sandbox Code Playgroud)\n解析数组键值对仅适用于没有空格的环境值(错误):
\nenv -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
)括起环境值也会出错:
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
变成了一个巨大的字符串
+ 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这是[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)