Twitter

Some bash tips -- 5 -- Protect and quote your variables

This blog is part of a bash tips list I find useful to use on every script -- the whole list of it can be found here.

Having non expected or wrong results in our scripts has to be avoided at all costs. This is why protecting and quoting your variables is so important as I will be showing below.

Protect your variables: (use ${VAR} instead of $VAR)
The $ character introduces what is called parameter expansion or variable expansion and this is why the variables have to be protected by braces (aka curly brackets): {}. Even if it is not always obviously useful, it is a good habit to have; to make it clear, let's have a look at the below example:
$ A="aaaa"
$ echo $A
aaaa
$ echo ${A}
aaaa
$
In this case, the behavior is the same whether we protect the "A" variable with curly brackets or not but if we introduce a second variable and combine it with the other variable:
$ A="aaaa"
$ B="bbbb"
$ echo $A$B
aaaabbbb        <== Expected result, all good
$ echo $A_$B
bbbb            <== Non expected result
The last line which is often used to dynamically create a variable or a filename (keep in mind that you should be using mktempfile to create tempfiles) has a non expected (wrong) result and this is because variable expansion happens after the $ sign and is then shown the A_ variable (which does not exist then is empty) and not the A variable. This is where variable protection is needed to avoid wrong results; as shown below, we will get the expected (and correct !) result by protecting our variables with curly brackets:
$ echo ${A}_${B}
aaaa_bbbb        <== This is the result you want
The above example has shown how crucial is to always protect your variables so take the habit of doing it even if the benefit of it does not always looks obvious at first sight. Keep in mind though to NOT protect special variables like $$, $?, etc ...

Quote your variables: (use $"{VAR}" instead of ${VAR})
You should quote your variables which contain characters but not integers nor shell special variables ($?, $@, $$, etc...); indeed, this protects spaces, empty string, special characters like "*" as shown by the below example:
$ touch "a*"                              <= create a file named "a*"
$ A="a*"
$ ls ${A}
'a*'   another_a.sh   another_backup.sh   <== Wrong
$ ls "${A}"
'a*'                                      <== Good
$

Another example with a file containing spaces:
$ touch "a file with space"          <== Create a file with spaces in the name
$ FILE="a file with space"
$ ls ${FILE}
ls: cannot access 'a': No such file or directory
ls: cannot access 'file': No such file or directory
ls: cannot access 'with': No such file or directory
ls: cannot access 'space': No such file or directory
# This is not the the expected result
$ ls "${FILE}"            <== Quote your variable
$ 'a file with space'     <== This is the file you are looking for


Quoting and protecting your variables is not an option and should always be done in order to avoid wrong results and then unexpected behaviors of your shell scripts. As one says, an image is worth 10000 words, so keep this one in mind:


< Previous bash tip / Next bash tip >

No comments:

Post a Comment

CUDA: Getting started on Google Colab

While getting started with CUDA on Windows or on WSL (same on Linux) requires to install some stuff, it is not the case when using Google...