Global and local scoping of variables

walden systems, geeks corner, programming, languages, Bash, scope, local scope, global scope, hoisting, functions, variables, developer, scripting
Bash is the GNU Project's shell. Bash is the Bourne Again SHell. Bash is an sh-compatible shell that incorporates useful features from the Korn shell (ksh) and C shell (csh). It is intended to conform to the IEEE POSIX P1003.2/ISO 9945.2 Shell and Tools standard. It offers functional improvements over sh for both programming and interactive use. In addition, most sh scripts can be run by Bash without modification.

Bash variables provide temporary storage for information that will be needed during the lifespan of the program. There shouldn't be any space around "=" sign in variable assignment. When you use VAR=VALUE, Bash sees the "=" as a symbol and treats the command as a variable assignment. When you use VAR = VALUE, Bash assumes that VAR must be the name of a command and tries to execute it. Similar to Python, Bash doesn't care about the type of variables. Variables could store strings, integers, or real numbers. To access the variables, just prefix the variable name with $, which will give you the value stored in that variable.

In Bash, like Python, variables do not have to be declared. But, when you access the variable which is not used so far, you will not get any warning or error message. Instead, it will display a blank value. Bash is a case sensitive environment so whenever you refer to a variable you must be consistent in your use of uppercase and lowercase letters.

Below are some ways to declare variables :

1    myArray=( 'John' 'Jane' David Robert 'John Doe' )
2    myString="Hello World"
3    myInteger=4
4
5    foo[0]="one"
6    foo[1]="two"
7    echo ${foo[1]}  
8    echo $foo      
9    echo ${foo[@]}  
10   echo ${foo[*]} 



After executing the code above, the variables hold the following :

    myArray hold 'John', 'Jane', 'David', 'Robert' and 'John Doe'. This is because "David Robert" is not in quotes so Bash sees it as two different entries and "John Doe" is enclosed in quotes so Bash sees it as a single entry.

    myString holds 'Hello World' since "Hello World" is in quotes and Bash sees this as a single entry.

    myInteger holds 4

    foo holds 'one', 'two'. The output of line 7 is 'two' since the element at array 1 is "two." The output of line 8 is 'one' since Bash treats having no index as having index 0. Both lines 8 and 9 have the output 'one' 'two' since the @ ad * allows you to access all the elements of the array

Special variables

There are special bash variables for grabbing arguments to scripts and functions:

$0
Holds the script name

$1 - $9
Holds the 9 arguments

${10}
Holds the tenth argument

$#
Holds the number of arguments

$?
Holds the "exit status" of the previously executed process.
    An exit status of 0 indicates the process "succeeded" without error.
    An exit status other than 0 indicates an error.

$$
Holds the process ID of the current script.

$USER
Holds the username of the user running the script.

$HOSTNAME
Holds the hostname of the machine the script is running on.

$SECONDS
Holds the number of seconds since the script was started.


Declare statement

We stated above that Bash does not require type to be defined. Although this is true, we can limit the type by using the declare statement. By using the declare statement in bash, we can limit the value assigned to the variables. It restricts the properties of variables. Option in a declare statement is used to determine the type of a variable.

The syntax is the following:

declare -i variable

Where -i is an option. Below are some options available :

-r read only variable
-i integer variable
-a array variable
-f for funtions
-x declares and export to subsequent commands via the environment.

Global variable scope

Variables are limited to the process they were created in, this is called scope. Normally this isn't an issue but sometimes, a script may run another script as one of its commands. If we want the variable to be available to the second script then we need to export the variable. Global variables can be set in another script such as .bashrc or .profile. Global variables are also called as environment variables, which will be available to all shells. printenv command is used to display all the environment variables. To access those variables, we use the export keyword.

    export HOME_PATH=/home/user1

Exporting variables is a one way process. The original process may pass variables over to the new process but anything that process does with the copy of the variables has no impact on the original variables.

In order to receive environment changes back from the script, we must source the script, this runs the script within our own interactive shell, instead of spawning another shell to run it.

    source .bashrc

Local variable scope

Local variables are visible only within the block of code. local is a keyword which is used to declare the local variables. In a function, a local variable has meaning only within that function block.

Local variables will have only empty value before and after calling the function. Its scope is only with in the function. It doesn't exist outside of the function, whereas the global variable will have updated value even after the function execution.

1    #!/bin/bash
2
3    VAR="global variable"
4    function myFunc 
5    {
6            local VAR="local variable"
7            echo $VAR
8    }
9    echo $VAR
10   myFunc
11   echo $VAR



Var in line 3 is a global variable and can be used anywhere in this Bash script.
The output of line 7 is "local variable".
The output of line 9 is "global variable" since VAR on line 3 and VAR on line 6 are two different variables.