Variables are named places to temporarily store data. We can set (or “declare”) a variable, which
assigns a value to it, or read a variable, which will “expand” or “resolve” it to its stored value.
We can declare variable values in a number of ways. The easiest method is to set the value directly
with a simple name=value declaration. Notice that there are no spaces before or after the “=” sign:
1 | kali@kali:~$ first_param=Super |
Declaring a variable is pointless unless we can reference it. To do this, we precede the variable with
the “$” character. Whenever Bash encounters this syntax in a command, it replaces the variable
name with its value (“expands” the variable) before execution:
1 | kali@kali:~$ first_param=Super |
Variable names may be uppercase, lowercase, or a mixture of both. However, Bash is casesensitive so we must be consistent when declaring and expanding variables. In addition, it’s good
practice to use descriptive variable names, which make our scripts much easier to read and
maintain.
Be advised that Bash interprets certain characters in specific ways. For example, this declaration
demonstrates an improper multi-value variable declaration:
1 | kali@kali:~$ greeting=Hello World |
This was not necessarily what we expected. To fix this, we can use either single quotes (‘) or double
quotes (“) to enclose our text. However, Bash treats single and double quotes differently. When
encountering single quotes, Bash interprets every enclosed character literally. When enclosed in
double quotes, all characters are viewed literally except “$”, “`”, and “" meaning variables will be
expanded in an initial substitution pass on the enclosed text.
A simple example will help clarify this:
1 | kali@kali:~$ greeting='Hello World' |
In this example, the single-quote-enclosed declaration of greeting preserved the value of our text
exactly and did not interpret the space as a command delimiter. However, in the double-quoteenclosed declaration of greeting2, Bash expanded $greeting to its value (“Hello World”), honoringthe special meaning of the “$” character.
We can also set the value of the variable to the result of a command or program. This is known as
command substitution, which allows us to take the output of a command or program (what
would normally be printed to the screen) and have it saved as the value of a variable.
To do this, place the variable name in parentheses “()”, preceded by a “$” character:
1 | kali@kali:~$ user=$(whoami) |
Here we assigned the output of the whoami command to the user variable. We then
displayed its value. An alternative syntax for command substitution using the backtick, or grave,
character (`) is shown below:
1 | kali@kali:~$ user2=`whoami` |
The backtick method is older and typically discouraged as there are differences in how the two
methods of command substitution behave. It is also important to note that command
substitution happens in a subshell and changes to variables in the subshell will not alter variables
from the master process. This is demonstrated in the following example:
1 | kali@kali:~$ cat ./subshell.sh |
In this example, first note that we changed the shebang, adding in the -x flag. This instructed Bash
to print additional debug output, so we could more easily see the commands that were executed
and their results. As we view this output, notice that commands preceded with a single “+” character
were executed in the current shell and commands preceded with a double “++” were executed in a
subshell.
This allows us to clearly see that the second declarations of var1 and var2 happened inside a
subshell and did not change the values in the current shell as the initial declarations did.