1

In the following script, a function (g) has the value of its local variable (i) overwritten by a function (f) it calls.

#!/usr/bin/env bash

f() {
    #local i # Let's assume whoever wrote this function f forgot,
             # to declare its variables as being local to it
    i=0
}

g() {
    local i # How to declare i as being only modifiable in the
            # scope of g, but not by functions g calls?
    for i in 1 2 3; do
        f # overwrites the value of i with 0
        echo "i: $i"
    done
}

g

# output:
# i: 0
# i: 0
# i: 0

Is there a way to restrict the exposure of bash variables to the scope they are declared in?

Is there a way, to make variables function-local by default, if someone does not declare them as being global explicitely (e.g. with declare -g)?

1 Answer 1

2

The only way is to run the troublesome code in a subshell:

g() {
    local i 
    for i in 1 2 3; do
        (f)           # <<
        echo "i: $i"
    done
}
i: 1
i: 2
i: 3

Variables are global unless they are declared local. There's no avoiding that.


Oh, I forgot a very important aspect of local that is directly affecting this scenario: a "local" variable declared in g is read-write-able in g and in any function called from g (to any depth).

  • variable i in f is in the local scope of g.

From the manual (my emphasis):

local can only be used within a function; it makes the variable name have a visible scope restricted to that function and its children.


quite tangentially, Perl has this same "problem" with its local command that was solved by a new my command:

$ perl -e '
  sub f { $i = 10; }
  sub g { local $i = 5; f; print "$i\n"; }
  # ......^^^^^
  g
  '
10

$ perl -e '
  sub f { $i = 10; }
  sub g { my $i = 5; f; print "$i\n"; }
  # ......^^
  g
  '
5
3
  • Well, i is declared local in g, but I get what you mean. I think this is a good solution, although one does not want to invoke a subshell in some cases.
    – anick
    Oct 25, 2022 at 18:38
  • 1
    Please see edit Oct 25, 2022 at 18:49
  • 1
    Good to know this about Perl! I bet this will save me some headaches in the future :) If only Bash had such a 'my' specifier too.
    – anick
    Oct 25, 2022 at 18:57

You must log in to answer this question.

Not the answer you're looking for? Browse other questions tagged .