Difference Between Shell and Environment Variables

What is the difference between an inline variable assignment and a regular one in Bash?

The format VAR=value command sets the variable VAR to have the value value in the environment of the command command. The spec section covering this is the Simple Commands. Specifically:

Otherwise, the variable assignments shall be exported for the execution environment of the command and shall not affect the current execution environment except as a side-effect of the expansions performed in step 4.

The format VAR=value; command sets the shell variable VAR in the current shell and then runs command as a child process. The child process doesn't know anything about the variables set in the shell process.

The mechanism by which a process exports (hint hint) a variable to be seen by child processes is by setting them in its environment before running the child process. The shell built-in which does this is export. This is why you often see export VAR=value and VAR=value; export VAR.

The syntax you are discussing is a short-form for something akin to:

VAR=value
export VAR
command
unset -v VAR

only without using the current process environment at all.

What's the difference between env and set (on Mac OS X or Linux)?

Long story short: set can see shell-local variables, env cannot.

Shells can have variables of 2 types: locals, which are only accessible from the current shell, and (exported) environment variables, which are passed on to every executed program.

Since set is a built-in shell command, it also sees shell-local variables (including shell functions). env on the other hand is an independent executable; it only sees the variables that the shell passes to it, or environment variables.

When you type a line like a=1 then a local variable is created (unless it already existed in the environment). Environment variables are created with export a=1

What is the difference between global scope and environment?

TL;DR The global scope is initialized from the environment at startup, but is not the same as the environment.


The environment is a set of strings of the form <name>=<value> provided by the parent process. On startup, the shell takes each string whose <name> portion is a valid shell identifier and creates a variable in the global scope with that name.

For example, an environment string FOO=3 becomes a shell variable named FOO with the value 3.

On the other hand, an environment string like 10=6 is ignored by the shell, because 10 is not a valid shell identifier. The string remains in the environment, though, to be passed on to any child processes that might expect such a string. [UPDATE: The POSIX spec does not require such strings to be ignored; a conforming shell could either keep or discard them.]

There are also local variables, created by commands like local and declare inside a function definition. For example:

$ foo () { declare x; x=3; echo "$x"; }
$ x=2
$ foo
3
$ echo "$x"
2

x=2 created (or changed the value of) a variable in the global scope. Inside the function, declare x created a local variable. Changes to that variable did not affect the global by the same name.

The -g option to declare lets you make the name x inside the function refer to the global scope, rather than creating a local variable.

$ foo () { declare -g x; x=3; echo "$x"; }
$ x=2
$ foo
3
$ echo "$x"
3

How to check if an environment variable exists and get its value?

[ -z "${DEPLOY_ENV}" ] checks whether DEPLOY_ENV has length equal to zero. So you could run:

if [[ -z "${DEPLOY_ENV}" ]]; then
MY_SCRIPT_VARIABLE="Some default value because DEPLOY_ENV is undefined"
else
MY_SCRIPT_VARIABLE="${DEPLOY_ENV}"
fi

# or using a short-hand version

[[ -z "${DEPLOY_ENV}" ]] && MyVar='default' || MyVar="${DEPLOY_ENV}"

# or even shorter use

MyVar="${DEPLOY_ENV:-default_value}"

Use environment variable in word within command


  • There are no environment variables in your code, only shell variables.

    • Shell variables may also be environment variables (exported variables such as $PATH that are visible to all child processes, whether they're shells or not), but that's not the case here.
  • Shell variable names must be disambiguated from adjacent characters that could be part of a syntactically legal variable name by enclosing them in {...} - ${i}, in your case.

  • Unless you specifically want shell-variable references (possibly embedded in unquoted tokens) subjected to shell expansions, notably word-splitting and globbing, double-quote them - "s${i}a" in your case.

  • Use an arithmetic, C-style loop to create a memory-efficient loop with a variable number of iterations.

To put it all together:

$ n=5; for (( i = 1; i <= n; ++i )); do echo "s${i}a"; done
s1a
s2a
s3a
s4a
s5a

environmental variables vs. global variables

They don't mean the same. "global" is a programming language idea, "environment variable" is an operating system idea. So, they're not really related, and conceptually quite different!

Since you now know that, and both terms are easily researchable ("environment variable" on wikipedia, global variable on the Python.org language tutorial), I'm not going to write an introduction into two completely unrelated topics here – I simply couldn't put it any better.

Note that as Python beginner, you will not have to deal with explicitly global variables often. In fact, global is usually a keyword you should avoid, it often is a sign that you forgot to correctly think of what goes in and out of a function.



Related Topics



Leave a reply



Submit