58

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
  • 12
    Upvoted as a proxy-vote nominating envsubst as worst man-page ever.
    – MarkHu
    Sep 1, 2021 at 16:41

4 Answers 4

52

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
  • 5
    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
21

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
  • 1
    @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

You must log in to answer this question.

Not the answer you're looking for? Browse other questions tagged .