Bash

如何為命令動態設置環境變數?

  • July 22, 2022

我想使用某種帶有純 bash 的簡約模板引擎和envsubst

user@host:~$ env -i FOO=foo BAR="bar baz" envsubst '$FOO,$BAR' \
 <<< 'Hello "$FOO" and "$BAR"!'
Hello "foo" and "bar baz"!

上面的作品,但只包含靜態變數。

現在讓我們假設環境變數是動態給出的,就像關聯數組一樣:

declare -A MY_ENV=([FOO]=foo [BAR]="bar baz")

解析數組鍵值對僅適用於沒有空格的環境值(錯誤):

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

嘗試用引號(注意 '%s' 而不是%s )包裝環境值也會出錯:

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

的輸出set -x原因:set -x表明參數 forenv變成了一個巨大的字元串

+ env -i 'FOO='\''foo'\''' 'BAR='\''bar' 'baz'\''' envsubst #...
env: ‘baz'’: No such file or directory

我一定錯過了一個shell逃生課程(再次……)。我如何重寫最後一個範例以正常工作?

這是$$ 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"!'
Hello "foo" and "bar baz"!

請注意我沒有註入任何額外的引號字元。


擴展至因此我們不必對變數名進行硬編碼:

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"!'

引用自:https://unix.stackexchange.com/questions/710935