54

When I stumbled upon envsubst I wanted to use it for replacing only specific variables and suspected that the SHELL-FORMAT parameter might be what is wanted but I cannot get it to work.

Unfortunately, the man and info pages don't give any usage example and only say

If a SHELL-FORMAT is given, only those environment variables that are referenced in SHELL-FORMAT are substituted

Which does not tell me how to reference them.

1
  • 7
    Upvoted as a proxy-vote nominating envsubst as worst man-page ever.
    – MarkHu
    Sep 1, 2021 at 16:41

4 Answers 4

48

As indicated by the text, you just have to reference (e.g. by $VARNAME or ${VARNAME}) the variables as in a usual shell command. However, you have to make sure that the shell does not expand them beforehand.

Here are some examples to illustrate this (assuming export FOO=BAR):

$ echo '$FOO$FOO2' | envsubst
BAR

As you can see, $FOO2 has been replaced by "" as it was not defined. Now we can restrict that replacement to only $FOO by:

$ echo '$FOO$FOO2' | envsubst '$FOO'
BAR$FOO2

using "" instead of '' would lead to substitution before it is wanted:

echo '$FOO$FOO2' | envsubst "$FOO"
$FOO$FOO2

(This amounts to the effective call envsubst "BAR" which detects no variables so none are replaced.)

As the man-page said, all variables that are referenced in SHELL-FORMAT are replaced, so we can even do this:

echo '$FOO$FOO2$FOO3' | envsubst '$FOO some more text ${FOO3}'
BAR$FOO2

As you can see, the SHELL-FORMAT is quite flexible.

Finally, the parameter --variables allows you to evaluate which variables are selected for substitution by the SHELL-FORMAT:

envsubst --variables '$FOO some more text ${FOO3}'
FOO
FOO3

In the premature substitution example from above this would have shown the error:

$ envsubst --variables "$FOO"
(empty string returned)

As stated in the man-page, envsubst does not process any stdinput when --variables is present.

1
  • 2
    At this point, I still don't understand when/why anyone would ever want to use the envsubst --variables '$FOO blah' command. This illustrates how a technically accurate/precise man-page can be almost useless if it lacks examples or explanation.
    – MarkHu
    Sep 1, 2021 at 16:48
20

Here are some examples that helped me understand how to use it properly. It was surprising to me that envsubst only replaces variables mentioned in the parameter.

export FOO_X="value_x"
export FOO_Y="value_y"
export FOO_Z="value_z"


$ echo 'x=$FOO_X y=$FOO_Y z=${FOO_Z}' | envsubst
x=value_x y=value_y z=value_z

$  echo 'x=$FOO_X y=$FOO_Y z=${FOO_Z}' | envsubst '$FOO_X'
x=value_x y=$FOO_Y z=${FOO_Z}

$ echo 'x=$FOO_X y=$FOO_Y z=${FOO_Z}' | envsubst '$FOO_X $FOO_Z'
x=value_x y=$FOO_Y z=value_z

$ echo 'x=${FOO_X} y=${FOO_Y} z=${FOO_Z}' | envsubst '$FOO_Z ${FOO_Y}'
x=${FOO_X} y=value_y z=value_z

$VAR and ${VAR} both seem to work btw. Order does not matter.

I did not understand what SHELL-FORMAT meant either, still don't know why it is named like that. But after the above experiments I think I know what it does.

1
  • 1
    This help me a lot after read those example, from man help and info, only know SHELL-FORMAT exist, but don't know how to declare it!
    – zw963
    Sep 21, 2018 at 15:12
3

The verbiage is a bit confusion. To reword the help text more meticulously:

SHELL-FORMAT is an optional text command line argument containing references to environment variables. To reference an environment variable in the text, prefix the variable name with a $. For example: Hello $FOO World $BAR references environment variables FOO and BAR. The rest of the string is ignored. If the SHELL-FORMAT command line argument is present, then when variable substitution occurs on text received through stdin, it will be limited to variables referenced in the SHELL-FORMAT command line argument.

So to answer your question explicitly: Prefix the variable name with $.

-1

I found it paritcularly useful for this...

    cat myfile|envsubst '$(env|grep AJN)'

This substitutes all the variables which are currently defined in my environment (env), and which contain AJN (My initials.), but leaves all the rest of the variables alone.

2
  • This is useless since most variable names in env are not prefaced by $, and so envsubst will ignore all of them. Oct 6, 2021 at 12:36
  • @user1220323 You're onto something, but the syntax needs to be fixed. This should work: cat myfile | envsubst "\$$(env | grep AJN | cut -d = -f 1 | awk 1 ORS=' $')" or cat myfile | envsubst "$(env | grep AJN | cut -d = -f 1 | sed 's/^/$/' | tr '\n' ' ')"
    – bmaupin
    Aug 10, 2022 at 19:28

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.