trysis
trysis

Reputation: 8416

Bash Variable Scope Leak

Usually, I see questions about people not being able to access variables from outside their scope. However, I seem to be experiencing the opposite: I am seeing variables still having values from inner scopes they should have given up afterwards. For example (making svn aliases similar to git aliases):

function svn() {
    case $@ in
        alias*) shift 1;
            for i in "$@"; do
                if [[ "$i" == "-t" ]];
                then
                    j="$i,$j"
                elif [[ "$i" == "-f" ]];
                    k="$i,$j"
                fi
            done

            echo "i = $i"
            echo "j = $j"
            echo "k = $k"
        ;;
    esac
}

I put this in a script and source it, so its function is made into an alias for bash (I think). Try running this with various combinations of "-t" and "-f", and you'll see that the variables "$i", "$j", and "$k" all keep their values when running the script again, and that they stay the same in the outer shell, after the script has exited. I am using an Ubuntu 15.04 laptop, and when I type Ctrl-X Ctrl-V my shell outputs GNU bash, version 4.3.30(1)-release (x86_64-pc-linux-gnu).

Everything I have read about bash tells me this should not happen (admittedly, I am somewhat of a beginner in this area). Variables should not stay set after the script (or function) exits, unless you use export on them, which I have not. So why is this happening?

Upvotes: 4

Views: 1205

Answers (1)

John Kugelman
John Kugelman

Reputation: 361585

There are two different phenomena in play:

  1. When variables are exported, they are copied into the environments of child processes. Non-exported variables are not passed on. Variables aren't exported unless you explicitly use export to mark them for export.

     export LESS_OPTIONS=-R   # export so `less` sees this variable
     less
    

    Don't confuse this with scope, which is different.

  2. Inside functions variables have global scope by default. You have to use the local keyword to declare local variables. Otherwise a loop like for i in "$@" will modify the global variable $i rather than creating a local variable.

    svn() {
        local i j k
    
        case $@ in
            ...
        esac
    }
    

Exporting determines what child processes see. Scope determines whether functions modify global variables or not.

Upvotes: 6

Related Questions