Scenario:
$ cat t426.sh
set -x
f()
{
local x="x"
eval $1=$x
}
x="y"
f x
echo $x
$ bash t426.sh
+ x=y
+ f x
+ local x=x
+ eval x=x
++ x=x
+ echo y
y
Here we see that y
is printed. I expect that x
is printed.
If I change the name of the local variable from x
to x_
, then x
is printed.
Why local variable is not assigned to a non-local variable with the same name?
How to fix, so that local variable has the same name as a non-local variable?
Assumptions:
f()
input is the name of a global variablef()
resets the value of the global variable (in this case always setting to the string 'x'
)With bash 4.3+
we have access to the nameref
feature which functions like a symlink to a (global) variable.
$ cat myscript
#!/bin/bash
f() {
local -n _var=$1 # -n == nameref
_var="x"
}
a=3
b="y"
echo "### before:"
typeset -p a b
f a
f b
echo "### after:"
typeset -p a b
Addressing OP's issue - local variable has the same name as a non-local variable
- instead of a local variable with a constantly changing name (to match the global variable), you have a statically named local variable (_var
) which acts as a symlink to the global variable.
Taking for a test drive:
$ ./myscript
### before:
declare -- a="3"
declare -- b="y"
### after:
declare -- a="x"
declare -- b="x"