Blindly relying on some statement claiming 'use unset-v or strange things will happen', I've been using unset -v
since.
Now I've encountered following problem in conjunction with name references, where a referenced var is unset, too:
gitStatus=$(git status --porcelain=v1)
declare -n gitStatusResult=gitStatus
unset -v gitStatusResult
echo -e "GIT_STATUS: ${gitStatus[@]}"
gitStatus will be empty, too after that, not just gitStatusResult.
When using unset -n gitStatusResult
or simply gitStatusResult=
instead, the content of gitStatus will be preserved.
unset --help
states, that:
-v treat each NAME as a shell variable
-n treat each NAME as a name reference and unset the variable itself rather than the variable it references
This was unexpected - in my understanding things should be just the other way round, where -n
should unset gitStatus directly, and -v
should only unset the named reference gitStatusResult.
EDIT:
In addition, when using unset -n gitStatus
, neither gitStatus nor gitStatusResult appear empty.
Could somebody shed some light on this issue?
I'm using Cygwin GNU bash, version 5.2.21(1)-release
.
This is, I believe, the intended behavior of a nameref. A nameref is just that: a reference to a name, not a "real" variable itself. Anything you do to or with a nameref is equivalent to doing the same to or with the underlying variable.
foo=1
declare -n fooRef=foo
echo $fooRef # same as echo $foo
fooRef=2 # same as foo=2
[[ -v fooRef ]] # same as [[ -v foo ]]
unset -v fooRef # same as unset -v foo
Note that the reference in the last case outlives the original variable; you can still use fooRef
to revivify foo
:
fooRef=5 # still the same as foo=5
As such, if you want to remove the nameref, you need some way to address it directly; that's what unset -n
is for, bypassing the ordinary behavior of a nameref.
bash-5.2$ foo=1
bash-5.2$ declare -n fooRef=foo
bash-5.2$ declare -p foo fooRef
declare -- foo="1"
declare -n fooRef="foo"
bash-5.2$ unset -n fooRef
bash-5.2$ declare -p foo fooRef
declare -- foo="1"
bash: declare: fooRef: not found