pmor
pmor

Reputation: 6286

Why local variable is not assigned to a non-local variable with the same name?

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?

Upvotes: 2

Views: 127

Answers (2)

markp-fuso
markp-fuso

Reputation: 35076

Assumptions:

  • f() input is the name of a global variable
  • f() 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"

Upvotes: 3

glenn jackman
glenn jackman

Reputation: 247042

An alternate way to do this is to use the (ironic) -g "global" option to the local command.

f() {
  local -g "$1"="from function"
}

x="global scope"
declare -p x

f x
declare -p x

outputs

declare -- x="global scope"
declare -- x="from function"

Upvotes: 4

Related Questions