나는 순수한 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
원래 게시물에서 동적 빌드 매개변수가 작동하지 않는 이유가 여전히 궁금합니다. 도움을 주시면 감사하겠습니다.)