is there an escape character for envsubst?

Is there a way to prevent envsubst from substituting a $VARIABLE? For example, I would expect something like:

export THIS=THAT
echo "dont substitute \\\$THIS" | envsubst

and have it return

dont substitute $THIS

but instead I get

dont substitute \THAT

is there any escape character for doing this?


Solution 1:

If you give envsubst a list of variables, it only substitutes those variables, ignoring other substitutions. I'm not exactly sure how it works, but something like the following seems to do what you want:

$ export THIS=THAT FOO=BAR
$ echo 'dont substitute $THIS but do substitute $FOO' | envsubst '$FOO'
dont substitute $THIS but do substitute BAR

Note that $THIS is left alone, but $FOO is replaced by BAR.

Solution 2:

export DOLLAR='$'

export THIS=THAT
echo '${DOLLAR}THIS' | envsubst

Or more clear:

export THIS=THAT
echo '${DOLLAR}THIS' | DOLLAR='$' envsubst

Solution 3:

My workaround is as follows:

Original template:

$change_this
$dont_change_this

Editted template:

$change_this
§dont_change_this

Now you can process:

envsubst < $template | sed -e 's/§/$/g'

This relies on the character § not occurring anywhere else on your template. You can use any other character.

Solution 4:

$ echo $SHELL
/bin/bash
$ echo \$SHELL
$SHELL
$ echo \$SHELL | envsubst 
/bin/bash
$ echo \$\${q}SHELL | envsubst 
$SHELL

So doing $$ allows you to add a $ character. Then just "substitute" non-existent variable (here I used ${q} but can be something more meaningful like ${my_empty_variable} and you'll end up with what you need.

Just as with the paragraph solution - you need something special - here... a non-existent variable, which I like a bit more than performing additional sed on templates.

Solution 5:

If there's only one or two variables you don't want to expand, you can sort of whitelist them by temporarily setting them to their own name, like this:

$ echo 'one $two three $four' | four='$four' envsubst
one  three $four

Here, the $four variable gets replaced with $four, effectively leaving it unchanged.