Feature Request / Possible bug: Support nested variables enclosed by raw string
I have a weird issue where envsubst is not working as expected.
When I add only a single a default variable to the right side of the experssion it will work similarly as a default POSIX shell. But when I add additional text to the default it start to do some strange behaviour.
I'll provide some examples, I believe that will be the best description.
sh use case:
docker run --rm -it debian:buster-slim sh
# export VAR1="shouldevaluate"
# export EMPTY_VAR=""
# export MAIN_VAR="${EMPTY_VAR:-$VAR1}"
# echo $MAIN_VAR
shouldevaluate
#
#
# export MAIN_VAR="${EMPTY_VAR:-asdqwe$VAR1}"
# echo $MAIN_VAR
asdqweshouldevaluate
#
#
# export MAIN_VAR="${EMPTY_VAR:-asdqwe $VAR1 qweasd}"
# echo $MAIN_VAR
asdqwe shouldevaluate qweasd
#
#
# export MAIN_VAR="${EMPTY_VAR:-asdqwe${VAR1}qweasd}"
# echo $MAIN_VAR
asdqweshouldevaluateqweasd
And this happens when I try to use the same method in envsubst.
# cat test.template
name = ${EMPTY_VAR:-$VAR1}
name = ${EMPTY_VAR:-asdqwe$VAR1}
name = ${EMPTY_VAR:-asdqwe $VAR1 qweasd}
name = ${EMPTY_VAR:-asdqwe${VAR1}qweasd}
#
#
# envsubst < test.template
name = shouldevaluate
name = asdqwe$VAR1
name = asdqwe $VAR1 qweasd
name = asdqwe${VAR1qweasd}
Would it be possible to add this feature?
Just chiming in with my own experience.
The README only shows support for ${VAR}, with any fallback value as $VAR..
-
${VAR}is not supported between outer braces and fails too. - The fallback must start with $ to qualify for evaluation as a variable, but since `${VAR} isn't supported, it can't distinguish from anything after it
- As shown above, when
$is used after the first character, it doesn't qualify and is treated as a raw string. If there is a}present, that'll get stripped away while the actual outer}is left as raw text.
#! /bin/bash
export LDAP_BIND_DN=nested_var
export SASLAUTHD_LDAP_FILTER=testing
# sed removes the lines with empty values:
/tmp/envsubst < /tmp/test.conf | sed '/^.*: $/d' > /tmp/saslauthd.conf
With /tmp/test.conf as input (stdin):
ldap_servers: ${SASLAUTHD_LDAP_SERVER:=${LDAP_SERVER_HOST}}
ldap_auth_method: ${SASLAUTHD_LDAP_AUTH_METHOD:=bind}
ldap_bind_dn: ${SASLAUTHD_LDAP_BIND_DN:=${LDAP_BIND_DN}}
ldap_bind_pw: ${SASLAUTHD_LDAP_PASSWORD:=${LDAP_BIND_PW}}
ldap_search_base: ${SASLAUTHD_LDAP_SEARCH_BASE:=${LDAP_SEARCH_BASE}}
ldap_filter: ${SASLAUTHD_LDAP_FILTER:=(&(mail=%u)(mailEnabled=TRUE))}
ldap_start_tls: ${SASLAUTHD_LDAP_START_TLS:=no}
ldap_tls_check_peer: ${SASLAUTHD_LDAP_TLS_CHECK_PEER:=no}
ldap_tls_cacert_file: ${SASLAUTHD_LDAP_TLS_CACERT_FILE}
ldap_tls_cacert_dir: ${SASLAUTHD_LDAP_TLS_CACERT_DIR}
ldap_referrals: yes
log_level: 10
Results in /tmp//saslauthd.conf output:
ldap_servers: }
ldap_auth_method: bind
ldap_bind_dn: }
ldap_bind_pw: }
ldap_search_base: }
ldap_filter: testing
ldap_start_tls: no
ldap_tls_check_peer: no
ldap_referrals: yes
log_level: 10
We can see that all values with a default using ${VAR} became }, even when one was set ${LDAP_BIND_DN} for ldap_bind_dn:.
This works fine if using $LDAP_BIND_DN (no nested braces used). Given the last output from other comments above (asdqwe${VAR1qweasd}), it seems that:
- The left-most brace is matched to the first closing brace.
- Then the default is evaluated which would be
${LDAP_BIND_DNpaired with remaining "plain-text"}(The 2nd}, aka right-most one). - Since this "variable" is not set, it's treated as empty and the remaining
}is left, since it's not considered part of the original${ ... }expression?
asdqwe${VAR1qweasd} also implies that the first } was removed, then everything to the left was treated as the fallback value, which if not starting as $ is not evaluated 🤷♂️ While if it is you get the output I experienced which'd fail to evaluate.