Bash includes a complex array of symbols, tokens, or metacharacters. Each of these characters has a unique and important function. They are a part of what makes Bash capable. Let's look at some frequently used tokens and metacharacters and clear up some confusion.
Quotes
Quotes are what allow Bash to separate commands from strings or pieces of data. Using it, Bash will try to not evaluate the text as if it has a special meaning. You can also use quotes as a way to group data so that Bash can look at them as a single thing. Depending on the context of use, you might want to use different types of quotes or no quotes at all.
Single quotes
You can use single quotes in string literals where you want to suppress interpolation and special treatment of backslashes as well as backticks. If you use single quotes, Bash will treat the text inside the quotes as a literal string and nothing else. No characters in the quotes will hold any special meaning.
Let's look at an example, where we print some text using single quotes:
$ echo '$HOME'
The output for this command is:
$HOME
Here, Bash prints the text without evaluating it. This is why it doesn't print the value held by the environment variable HOME.
Double quotes
Double quotes will suppress both word splitting and globbing. You can also use them in contexts where you want the literal to be treated as a string and not a regex. Double quotes are less restrictive than single quotes as Bash will still process some special characters like $, \, and `.
Let's look at the previous example but with double quotes:
$ echo "$HOME"
The output of this command is:
/home/hyper
But the following text will be treated as regular text:
$ echo "home alone"
So, the output will be:
home alone
But when should anyone not use quotes if they are so helpful? Let's talk about avoiding quotes.
No quotes
You can avoid using quotes when you are absolutely sure that there are no word-splitting or globbing issues. Or when you may want word-splitting and globbing to take place.
When you don't use quotes, Bash will try to evaluate the text and look for special characters or tokens. And in case there aren't any, Bash will simply take the text as a string and execute it accordingly. Here's an example without special characters.
echo Hello World;
Even though there aren't any quotes, the output will still be:
Hello World
Besides quotes, Bash also uses symbols like brackets and parentheses for various other purposes. Let's take a look at them.
Brackets and parentheses
Primarily there are three bracket types: parenthesis, curly braces, and square bracket. However, there are a bunch of combinations of brackets either alone, in pairs, or while using $ in front. These combinations are different in terms of functions and will yield different results. Let's look at them starting with the single parentheses.
Dollar single parentheses
The single parenthesis is used to execute commands placed within it in a separate instance or subshell. Meaning variable declarations and environment changes will be temporary. The output of the commands inside the parenthesis can be captured using the $ sign. It is particularly useful when you want to process the output of multiple Bash commands.
For example, assuming there is a directory with some files. Let's run the following snippet of Bash commands:
FILE='workinfo.txt'
(FILE=banana; rm $FILE)
echo $FILE
The output for this command will be:
rm: cannot remove 'banana': No such file or directory
This means the rm command is executed in the context where FILE contains the value banana. After this, if you try to see the value held by FILE variable using echo $FILE, you'll get
workinfo.txt
You can also use $ sign in front of the parenthesis to save the output of commands within it to a variable. This allows you to interpolate output from subshell commands to a string.
Dollar double parentheses
The double parenthesis is used for arithmetic operations. It gives an exit code based on the result. If the result is non-zero then the exit code will be 0 else the exit code will be 1. If you wish to save the exact output of the operation to a variable, you must use the $ sign.
Let's look at a simple mathematical operation:
a=58
RESULT=$((a/2))
echo $RESULT
The output for the commands above is:
29
You can interpolate the output with the help of $ sign. This means you can further process the result of the operation. However, you can't work with decimal numbers using double parenthesis.
Take a look at another example:
RESULT="58 divided by 2 is $((58/2))."
echo $RESULT
The output will be:
58 divided by 2 is 29.Dollar braces
You can use braces to make a list of strings that can be used for expansion.
echo {of,by,for}" the people,"
The command shown above gives the following output:
of the people, by the people, for the people,
You can also use dollar braces for string interpolation. You can place variables within strings and Bash will replace the variable with its respective value.
FOOD="burger"
echo "I eat ${FOOD}s"
This example shows string interpolation and gives the following output:
I eat burgers
String interpolation is helpful because you can't use echo "I eat $FOODs" as it gives an error.
Single square brackets
The single square bracket is an alternative to the built-in test command for Bash. It can be used to compare two variables or values. In short, use this to check if a statement is true or false.
VAR1=2
VAR2=3
if [ $VAR1 -lt $VAR2 ]
then
echo "$VAR2 is greater than $VAR1"
else
echo "$VAR1 is greater than $VAR2"
fi
Since VAR1 is less than VAR2. The result is:
$VAR2 is greater than $VAR1
Bash provides you with many arguments to test values, compare them, see if they exist, analyze file modification dates, and much more. Take a look at this resource to learn more. This command provides a lot of features but there is another more versatile approach that involves using double square brackets.
Double square brackets
The double square bracket is similar to a single square bracket but it is more versatile and supports some additional features like regex and pattern expansion. It also suppresses word-splitting.
However, double square brackets is a keyword and not a command. This means double square brackets can take operators in contrast to single square brackets that can only accept arguments. Single square brackets look for arguments within them. So, you can't include operators and expect an output. In contrast, you can chain/include other keywords within double square brackets to evaluate expressions before processing them further.
On top of this, you can also use pattern matching. Take a look at the example below:
name="Alice"
[[ $name = *c* ]] && echo "Name includes c"
echo $?
Since string Alice contains the letter — c, the output will be 0.
Conclusion
In this topic, we discussed various types of quotes and brackets. To summarize:
- Use double quotes when you want to suppress word splitting and globbing. Also, in contexts where you want the literal to be treated as a string, not a regex.
- Use single quotes if you want to be more stringent and suppress interpolation as well as special treatment of backslashes.
$(())— double dollar parentheses can be used for arithmetic operations.$()— single dollar parentheses can be used to execute commands in a separate instance or subshell.${}— dollar braces can be used for expansion.- Both single square brackets and double square brackets can help you compare values. However, double square brackets —
[[]]is more versatile.