1

Wanted to validate my understanding of why these situations behave differently:

I think #1 happens because the assignment and echo run as a single command in the shell and $SOME_VAR is not set when echo executes (shell expands all variables before execution).

#1
$ unset SOME_VAR
$ SOME_VAR=abcdef  echo $SOME_VAR # prints nothing

I think #2 happens because the assignment and echo run as two separate commands in the same shell and $SOME_VAR is set in the shell when echo executes.

#2
$ unset SOME_VAR
$ SOME_VAR=abcdef   ; echo $SOME_VAR
abcdef

I don't understand why #3 happens.

#3
$ unset SOME_VAR
$ SOME_VAR=abcdef   ./test.sh # prints abcdef 
abcdef

I think #4 happens because assignment and execution of shell script execute as two different commands in the parent shell and the child shell that executes commands in test.sh does not inherit SOME_VAR (since there is no export statement).

#4
$ unset SOME_VAR
$ SOME_VAR=abcdef   ; ./test.sh # prints nothing

test.sh contains:

$ cat test.sh
#!/bin/bash

echo $SOME_VAR
Charles Duffy
  • 280,126
  • 43
  • 390
  • 441
Ankur Agarwal
  • 23,692
  • 41
  • 137
  • 208
  • To understand what's happening, you can look at what variables are available in the environment a script is running in; if you add `env | grep 'SOME_VAR'` to `test.sh`, you'll see what's different. – Benjamin W. Mar 20 '19 at 18:38
  • 2
    Mostly, #3 adds `SOME_VAR` to the environment of the subprocess, but #4 doesn't. If you change #4 to `export SOME_VAR=abcdef; ./test.sh`, it'll print the value. – Benjamin W. Mar 20 '19 at 18:39

1 Answers1

2

Example 1 happens because variable expansion happens first. The order of events in this case is:

  1. Expand $SOME_VAR (to an empty string)
  2. Set SOME_VAR to abcdef
  3. Call echo (with no args because $SOME_VAR expanded to an empty string)

Example 2 happens, as you say, because the commands are run separately.

Example 3 happens because SOME_VAR is set to abcdef prior to calling ./test.sh, and is part of the environment that ./test.sh is run in. This is actually the purpose of the idiom VAR=value command. You want command to be able to use VAR, but you don't necessarily want every other command or subshell to see it.

Example 4 happens because SOME_VAR is a local variable in the current shell and has not been export-ed so that subshells can use it.

An Example 5 would then be:

unset SOME_VAR
export SOME_VAR=abcdef ; ./test.sh # prints abcdef
Mike Holt
  • 4,452
  • 1
  • 17
  • 24