6

I am trying to understand the following part about unset from https://unix.stackexchange.com/a/381782/674

unset in bash only unsets a variable if it has been declared in the current scope (leaves it declared though except in the global scope; it removes attributes and values and the variable is no longer array or hash; also note that on namerefs, it unsets the referenced variable). Otherwise, it just pops one variable layer from the stack mentioned above.

Bash manual doesn't mention anything related, or I miss it.

Could you explain with examples for

  • "only unsets a variable if it has been declared in the current scope"
  • "leaves it declared though except in the global scope".

    If unset a variable which is in a function's local scope, is the unset variable not just unset but also undeclared?

    If unset a variable which is in the global scope, is the unset variable just unset but still declared?

    How may I check if a variable is declared or not?

  • "Otherwise, it just pops one variable layer from the stack mentioned above."

    What do "otherwise" and "one variable layer" mean?

Thanks.

Tim
  • 101,790

1 Answers1

9

Best with examples:

$ bash -c 'a=0; f() { local -i a=1; unset a; typeset -p a; a=2; }; f; echo "$a"'
declare -- a
0

That's unset called on a variable declared in the same scope. It's properly unset. It's still declared (though it has lost attributes and value), it's still limited to that scope. You see that even though we do a a=2, that is still done on a a local to f, the one from the outer scope is not affected. That's good and what we want.

In:

$ ./bash -c 'a=0; f() { local a=1; g; a=2; }; g() { unset a; echo "$a"; }; f; echo "$a"'
0
2

You can see that unset a didn't unset a. Instead, it revealed the one underneath, the one from the outer scope. When g returns, f's a variable will no longer be local.

In bash 5+, that can be fixed by setting the localvar_unset option.

Note that it's even worse in mksh and yash where unset does that popping instead of unsetting even for variables that have been declared in the same scope. The first example with them gives:

typeset a=0
2

Further reading at: