Bash
如何為命令動態設置環境變數?
我想使用某種帶有純 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"!'