-1

I would love to know how bash' declare -n option works when given only a single argument.

For example:

declare -n z
echo "${z}"  # ""          (empty string as expected)
z="somevalue"
echo "${z}"  # ""          (empty string)

declare -n z
echo "${z}"  # ""          (empty string)
z="somevalue"
echo "${z}"  # somevalue   (huwh? How come z is now assigned a value?)

Why does it seem like the second declare call unsets the nameref attribute? How come that the second assignment operation seems to work but the first one doesn't?

I'm using bash version 5.0.17(1)-release

melvio
  • 762
  • 6
  • 24
  • Have you read e.g. https://unix.stackexchange.com/q/510220? This isn't programming-specific. – jonrsharpe Aug 07 '21 at 12:48
  • 3
    @jonrshape Thank you for your moderation. I did see the link before but - to my fault - I only read the accepted answer which does not answer that question. So I think it is valuable for documentation purposes to add a link to the helpful answer: https://unix.stackexchange.com/a/510342/391074 – melvio Aug 07 '21 at 13:07
  • @jonrshape. I've updated the question to be more specific and not be covered by other StackExchange questions. I hope that makes it more useful to the community. – melvio Aug 08 '21 at 13:02
  • I think this is fine; it's a question about the semantics of the `bash` scripting language. – chepner Aug 08 '21 at 13:03

1 Answers1

1

TL;DR: The first assignment fixes which variable z refers to. The second assignment changes the value of that variable. The second call to declare is essentially a no-op; you've already set the nameref attribute on z; doing so a second time changes nothing.


The first time you use declare, z is uninitialized and undefined. The first assignment to z (whether in the call to declare or subsequent to it) determines which variable z refers to.

$ declare -n z
$ echo $z

$ z=somevalue
$ declare -p z
declare -n z=somevalue

echo $z at this point produces no value because somevalue itself is undefined.

Your second call to declare doesn't really do anything to z:

$ declare -n z
$ declare -p z
declare -n z=somevalue

It's still a reference to the variable somevalue. But now your second assignment to z does something different: it assigns a value to the variable somevalue, so that now when you do echo $z, you see the value of the variable somevalue, just as if you had written echo $somevalue.

It's a little less confusing if we use a different value for the two assignments, so we can distinguish between the referenced variable and its value.

$ declare -n z
$ z=foo
$ declare -p z
declare -n z=foo
$ z=9
$ echo $foo
9
chepner
  • 497,756
  • 71
  • 530
  • 681
  • Great explanation because you precisely show how one can use `declare -p` to investigate what is going on. I wish my upvote would show up. Unfortunately, my reputation is not high enough yet. Thanks @chepner – melvio Aug 08 '21 at 13:36
  • I contacted Chet Ramey - a maintainer of GNU bash and GNU Readline - and he confirmed your answer. – melvio Aug 09 '21 at 16:49