명령에 대한 환경 변수를 동적으로 설정하는 방법은 무엇입니까?

명령에 대한 환경 변수를 동적으로 설정하는 방법은 무엇입니까?

나는 순수한 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 #...

환경 값을 따옴표로 묶으려고 하면( note 로 '%s'대체 ) 오류가 발생합니다.%s

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

출력 set -x: 원인: set -x표시된 인수가 env거대한 문자열이 되었습니다 .

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

나는 탈출 수업을 확실히 놓쳤습니다 (다시…). 마지막 예제가 올바르게 작동하도록 어떻게 다시 작성할 수 있습니까?

답변1

이것은[배쉬FAQ/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"!'

답변2

해결책은 export각 키-값 쌍을 하나씩 처리한 후 다음을 실행하는 것입니다 envsubst.

for k in "${!MY_ENV[@]}"; do export $k="${MY_ENV[$k]}"; done 
envsubst '$FOO,$BAR' <<< 'Hello "$FOO" and "$BAR"!'
#Hello "foo" and "bar baz"!

이 코드는 현재 환경을 오염시키는 것을 방지하기 위해 서브셸 내부에 배치될 수 있습니다.


(PS: env원래 게시물에서 동적 빌드 매개변수가 작동하지 않는 이유가 여전히 궁금합니다. 도움을 주시면 감사하겠습니다.)

관련 정보