I can't explain the following behavior of unset
:
#!/bin/bash
my_unset() { unset "$@"; }
fn1() { local var; unset var; var=1; }
fn2() { local var; my_unset var; var=2; }
var=0
fn1; echo "$var"
fn2; echo "$var"
0
2
edit: I would expect the result to be 1
2
It behaves that way on bash 3/4/5
, is it a bug?
update
Here's an other example that shows that using my_unset
doesn't make the variable global; it only removes the local variable from the current context:
#!/bin/bash
my_unset() { unset "$@"; }
fn1() { local var; my_unset var; var=1; }
fn2() { local var; fn1; echo "[fn2] var=$var"; }
var=0
fn2
echo "[global] var=$var"
[fn2] var=1
[global] var=0
CodePudding user response:
See Chet's answer back in year 2012:
Back a number of years ago (16, to be exact), bash behaved like you expect. Between bash-1.14 and bash-2.0, I changed it in response to a number of bug reports that complained that a variable declared local in a function wasn't local when assigned a value in the function after being unset. Bash keeps a placeholder in the function's variable context so subsequent references to that unset variable don't traverse back through the call chain. This placeholder affects functions called by the function unsetting the local variable in the way you would expect dynamic scoping to work.
This only affects the current function, though: an unset issued from farther down the call chain, as you discovered, will unset the local variable without creating a placeholder.