Home > Software design >  Strange behavior of `unset` for local variables
Strange behavior of `unset` for local variables

Time:11-12

I can't explain the following behavior of unset:

#!/bin/bash

my_unset() { unset "$@"; }

fn1() { local var;    unset var; var=1; }
fn2() { local var; my_unset var; var=2; }

var=0

fn1; echo "$var"
fn2; echo "$var"
0
2

edit: I would expect the result to be 1 2

It behaves that way on bash 3/4/5, is it a bug?


update

Here's an other example that shows that using my_unset doesn't make the variable global; it only removes the local variable from the current context:

#!/bin/bash

my_unset() { unset "$@"; }

fn1() { local var; my_unset var; var=1; }
fn2() { local var; fn1; echo "[fn2] var=$var"; }

var=0
fn2
echo "[global] var=$var"
[fn2] var=1
[global] var=0

CodePudding user response:

See Chet's answer back in year 2012:

Back a number of years ago (16, to be exact), bash behaved like you expect. Between bash-1.14 and bash-2.0, I changed it in response to a number of bug reports that complained that a variable declared local in a function wasn't local when assigned a value in the function after being unset. Bash keeps a placeholder in the function's variable context so subsequent references to that unset variable don't traverse back through the call chain. This placeholder affects functions called by the function unsetting the local variable in the way you would expect dynamic scoping to work.

This only affects the current function, though: an unset issued from farther down the call chain, as you discovered, will unset the local variable without creating a placeholder.

  • Related