Passing arguments by reference

It’s 2018, and this question deserves an update. At least in Bash, as of Bash 4.3-alpha, you can use namerefs to pass function arguments by reference:

function boo() 
{
    local -n ref=$1
    ref="new" 
}

SOME_VAR='old'
echo $SOME_VAR # -> old
boo SOME_VAR
echo $SOME_VAR # -> new

The critical pieces here are:

  • Passing the variable’s name to boo, not its value: boo SOME_VAR, not boo $SOME_VAR.

  • Inside the function, using local -n ref=$1 to declare a nameref to the variable named by $1, meaning it’s not a reference to $1 itself, but rather to a variable whose name $1 holds, i.e. SOME_VAR in our case. The value on the right-hand side should just be a string naming an existing variable: it doesn’t matter how you get the string, so things like local -n ref="my_var" or local -n ref=$(get_var_name) would work too. declare can also replace local in contexts that allow/require that. See chapter on Shell Parameters in Bash Reference Manual for more information.

The advantage of this approach is (arguably) better readability and, most importantly, avoiding eval, whose security pitfalls are many and well-documented.

Leave a Comment