Re: Is this the expected behaviour for nameref in Bash 4.4 now?

2016-10-28 Thread Jack Kuan
thank you for the insight, it's very helpful!

On Oct 28, 2016 10:01 AM, "Chet Ramey"  wrote:

On 10/20/16 2:45 PM, kjk...@gmail.com wrote:
> set -x
>
> var_123=123
> f() {
> while (( $# )); do
> shift
> local var=var_123
> local -n var=$var; : status is $?
> local -p
> : var is $var
> done
> }
>
> f one two
>
>
> Running above script gives the follow output:
>
> + var_123=123
> + f one two
> + ((  2  ))
> + shift
> + local var=var_123
> + local -n var=var_123

`var' is a local nameref with value var_123

> + : status is 0
> + local -p
> var=var_123
> + : var is 123

Since var is a nameref, it expands to $var_123, which is 123

> + ((  1  ))
> + shift
> + local var=var_123

var doesn't get unset; it's still a nameref with value var_123.  Setting
the local attribute on an existing local variable doesn't unset any of
the variable's attributes.  You have to actually unset the variable to
do that.

> + local -n var=123
> ./x.sh: line 10: local: `123': invalid variable name for name reference

So now you try to assign `123' as the value of a nameref.  That would
cause subsequent attempts to assign to var to attempt to create and
assign to a variable named `123', which is invalid.  Bash-4.3 didn't
have enough error checking and would create variables with invalid names
in situations like this.

> + : status is 1
> + local -p
> var=var_123

This is probably where the confusion comes.  `local -p' doesn't print other
variable attributes.  If you had used `declare -p | grep var=' between the
two calls to `local' you would have seen that `var' had the nameref
attribute.

> + : var is 123
> + ((  0  ))

Chet
--
``The lyf so short, the craft so long to lerne.'' - Chaucer
 ``Ars longa, vita brevis'' - Hippocrates
Chet Ramey, UTech, CWRUc...@case.eduhttp://cnswww.cns.cwru.edu/~
chet/


Re: Is this the expected behaviour for nameref in Bash 4.4 now?

2016-10-20 Thread Jack Kuan
Thanks for replying.

I was expecting that in the second iteration of the loop, the
local var=var_123  command would make var a normal variable again with
value "var_123"
and then the local -n var=$var would make var again a nameref to var_123.
This seems
to be the behavior of Bash 4.3.

But anyway, it's easy to work around by introducing another variable rather
than redefining the nameref var:

set -x

var_123=123
f() {
while (( $# )); do
shift
local var=var_123
local -n var_ref=$var
done
}

f one two


On Thu, Oct 20, 2016 at 4:02 PM, Dan Douglas  wrote:

> Yes that was an intentional change to require valid identifiers. I can't
> say it will always be that way or that there won't at some point be a
> workaround. You can stiill use `${!param}' for now to refer to positional
> parameters as you always could, but as usual that isn't useful if you
> want to assign by reference.
>