5

The bash manual says "The environment for any simple command or function may be augmented temporarily by prefixing it with parameter assignments". I also understand that exported variables are by default passed to subprocesses that bash creates. I'm testing some behaviours with non-exported variables, and what I don't understand is how it works when the assignments are followed by the ; operator, and then some other commands are executed.

My case is the following:

VAR=hello; echo $VAR prints "hello".

VAR=hello :; echo $VAR prints a newline.

VAR=hello; echo $VAR; bash -c 'echo $VAR' prints "hello" and a newline.

The question is, in the first and third command, why is VAR being expanded? They are different commands, with (apparently) no parameter assignments prefixed.

I've tried in bash 4.4.20 and 5.1.16, having the same behaviour on both.

2
  • Those first and third cases are just the simple expansion of a shell variable. If they wouldn't expand the assigned value of $VAR, it'd be impossible to use unexported variables for pretty much anything.
    – ilkkachu
    Commented Feb 10 at 21:12
  • You are misunderstanding the manual. The sentence "The environment for any simple command or function may be augmented temporarily by prefixing it with parameter assignments" is describing this syntax: VAR=hello command-that-uses-VAR. The variable assignment is not separated from the command with a seicolon.
    – Sotto Voce
    Commented Feb 10 at 23:01

1 Answer 1

7

It seems that you are basically asking about exporting and when something needs to be exported. Let's look at each of your examples:

  1. VAR=hello; echo $VAR: these are two commands, run in the same shell session. Since we are in the same session, the first variable assignment is enough and there is no need to export anything.

  2. VAR=hello :; echo $VAR: here too we have two commands in the same shell session but in this case, the variable was explicitly only set for the duration of the : command. So here, you didn't actually set the variable in your shell session, you only set it for that one command. So when you get back to the shell, the variable is unset hence the echo prints an empty line.

  3. VAR=hello; echo $VAR; bash -c 'echo $VAR': here we have one shell session in which you run VAR=hello and echo $VAR. You then start a new shell session, which will therefore not inherit unexported variables, and in that second session, the echo $VAR prints nothing. This is where exporting would have made a difference:

    $ var=hello; bash -c 'echo $var'
    
    $ export var=hello; bash -c 'echo $var'
    hello
    

Though as was pointed out in comments, : is a "special built-in", and so according to POSIX, the result of the assignment in VAR=hello : should persist in the shell environment after : returns. Bash doesn't do that in normal mode though, but does in POSIX mode, as does pretty much any other POSIX shell.

So unset VAR; VAR=hello :; echo "$VAR" does print hello in POSIX-mode bash (bash called with -o posix or --posix or with sh or anything/sh as its argv[0] or with POSIXLY_CORRECT or SHELLOPTS=posix in its environment), dash, yash, ksh or zsh in sh or ksh emulation. That would be different with e.g. true instead of :, since it's just a regular command (builtin or not).

0

You must log in to answer this question.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.