Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Why does shell builtin colon command ":" after variable assignment on same line cause empty string value to be assigned?

If I add the colon (:) builtin shell command after an assignment, the variable gets assigned to the empty string (""). Why does it behave like that? I expected it to have no effect.

    set -vx
    MyVar1='my var 1'  : colon comment here  # *** !!! This gets assigned to empty string!!!
    MyVar2='my var 2'  # hash comment here; this is fine

    echo "MyVar1 = [$MyVar1]"  # EXPECTED: 'my var 1'; ACTUAL: '' (empty string).  Why?
    echo "MyVar2 = [$MyVar2]"  # As expected.

: (a colon)
: [arguments]
Do nothing beyond expanding arguments and performing redirections. The return status is zero.
https://www.gnu.org/software/bash/manual/html_node/Bourne-Shell-Builtins.html

like image 762
Rob Bednark Avatar asked Aug 06 '19 11:08

Rob Bednark


People also ask

What does $# mean in bash?

$# is the number of positional parameters passed to the script, shell, or shell function. This is because, while a shell function is running, the positional parameters are temporarily replaced with the arguments to the function. This lets functions accept and use their own positional parameters.

Which symbol generate the process ID of the shell?

$$ is the pid (process id) of the shell interpreter running your script. It's different for each process running on a system at the moment, but over time the pid wraps around, and after you exit there will be another process with same pid eventually.As long as you're running, the pid is unique to you.


1 Answers

: is a built-in command which returns successfully (a shorthand version of true).

When you do a variable assignment on the same line as a command, the assignment is only valid for the duration of the command (this is typically used to run commands with temporary environment variables set).

So when you run:

MyVar1='my var 1'  : colon comment here

You are:

  • running the command :
  • passing arguments colon, comment and here (these are dropped by the command)
  • with the temporary variable assignment MyVar1='my var 1' (this has no effect on the command)

This behaviour is described in the spec:

A "simple command" is a sequence of optional variable assignments and redirections, in any sequence, optionally followed by words and redirections, terminated by a control operator.

...

If no command name results, variable assignments shall affect the current execution environment. Otherwise, the variable assignments shall be exported for the execution environment of the command and shall not affect the current execution environment (except for special built-ins).

As pointed out in the comments (thanks!), : is one of the special built-ins, which means that in a standards-compliant shell, the assignment should affect the current execution environment. By default, Bash doesn't comply with the spec in this sense, although you can make it do so by invoking it as sh (on systems where it is the default shell) or by using bash --posix:

$ bash -c 'foo=bar :; echo $foo'

$ sh -c 'foo=bar :; echo $foo'
bar
$ bash --posix -c 'foo=bar :; echo $foo'
bar
like image 144
Tom Fenech Avatar answered Sep 21 '22 22:09

Tom Fenech