How to Correctly Use Environment Variables on the Command Line

I always forget about how to use shell environment variable correctly. I think because I did not grasp the key concept. For example, here is the wrong approach:

1
2
$ FOO=foo BAR=bar echo foo is ${FOO} and bar is ${BAR}
foo is and bar is

The correct answer I was hoping for is:

1
foo is foo and bar is bar

Because what I frequently do is use environment variable inside shell script:

1
2
3
4
5
#!/usr/bin/env bash
#
# script.sh
echo foo is ${FOO} and bar is ${BAR}

then do:

1
2
$ FOO=foo BAR=bar ./script.sh
foo is foo and bar is bar

This works as expected because the environment variables are passed into the subshell that executing the script.

But why not the first or the wrong approach?

The reason is that shell expands the variable before the command being executed. To shell, the first approach looks like:

1
$ FOO=foo BAR=bar echo foo is and bar is

The environment variables FOO and BAR were expanded before the command was executed. Hence, no values were printed.

Creating a shell script is a method, but here are three more solutions and better ones:

1
$ FOO=foo BAR=bar; echo foo is ${FOO} and bar is ${BAR}

or replace the semicolon with boolean operator:

1
$ FOO=foo BAR=bar && echo foo is ${FOO} and bar is ${BAR}

or use a subshell:

1
$ FOO=foo BAR=bar sh -c 'echo foo is ${FOO} and bar is ${BAR}'

So, the key is that shell expands the environment variables before executing the command.