Why is my zsh doing this?
% MYVAR="hi" echo $MYVAR % MYVAR="$(date)" echo $MYVAR % export MYVAR="$(pwd)" % echo $MYVAR /Users/theonlygusti Why are the same-line environment variables apparently not set?
In the command
MYVAR="hi" echo $MYVAR the variable MYVAR is set to hi in the environment of the echo command. However, the echo command does not use this variable. It is the current shell that expands the $MYVAR argument on the command line before calling echo.
Therefore, if the MYVAR variable does not exist in the shell beforehand, that command will only output a newline character.
In your last example, you set the variable in the shell before calling echo with the expansion of $MYVAR on the command line. Since the variable is set to the result of $(pwd) at that point (it does not need to be exported), the shell replaces $MYVAR with that value before calling echo.
The difference between
variable=value some-command and
variable=value; some-command or the equivalent
variable=value some-command is that in the first case, the variable is set to a value in the environment of some-command, but not in the current shell, while in the second/third case, the variable is set in the current shell, and then some-command is called. If variable is additionally exported, then that variable would also be available in the environment of some-command, would it want to use that variable.
Example:
$ unset -v var Setting a variable at the same time as calling another command sets that variable in the command's environment, but not in the local environment:
$ var=1 sh -c 'printf "var is %s\n" "$var"' var is 1 $ printf 'var is %s\n' "$var" var is Setting a variable in the local environment, but not exporting it sets it locally only:
$ var=1; sh -c 'printf "var is %s\n" "$var"' var is $ printf 'var is %s\n' "$var" var is 1 Exporting the variable makes it available in child processes:
$ export var $ sh -c 'printf "var is %s\n" "$var"' var is 1 Note that
MYVAR=$(pwd) is the same as
MYVAR=$PWD eval, for instance: var=1 eval echo '$var', and show the difference between this and the new shell. For instance, when using eval, var=1; eval echo '$var' would still show the value of $var. eval should ideally take a single-quoted string: eval 'echo "$var"'. In the bash shell, you'll otherwise invoke the split+glob operation on the value of $var (test with var='1 * 4' in bash). I know this user is using zsh, but that may easily be missed by future readers that just read the answer.
echo ${MYVAR}instead (with {} ). I don't know how it works, though. Something to do with variable expansion I think.