Custom Shell Scripts
Variables and Quoting
You can play with shell variables in different powerful ways. Very likely, most of the time you will just need to quote those variables properly, so I'll look first at the three kinds of quotes you can use in Bash.
Single quotes ('
) tell the shell that everything inside them should be used "as is," without any processing. Double quotes ("
) tell the shell to replace the name of every variable inside the quoted string with its current value. Finally, backquotes (`
) tell the shell that the content of the string is a command that should be executed (but only after replacing variables with their values, as in the double quotes case!). An alternative syntax for backquotes is:
#> $(command)
The difference among the three types of quotes is evident in the following example, which you can try out on your system:
#> echo '$PWD' $PWD #> echo "$PWD" /home/marco/ #> echo `$PWD` bash: /home/marco/: Is a directory
The last command causes an error because the backquotes make the shell grab the value of $PWD
(/home/marco/
) and then execute /home/marco/
as if it were an executable program, which of course it is not.
Basically, variables in backquote-delimited strings let you build and execute different commands every time they are parsed, depending on the current status of (possibly many) other variables. This is a very powerful feature, especially when you consider that you can nest those strings into each other. In that case, remember to escape the inner backquotes with backslashes.
When quoting, you also have to be careful when you concatenate variables and constant strings. The reason is shown in these commands, which try to assemble a date from its year, month, and day components:
#> YEAR='2018' #> MONTH='11' #> DAY=10 #> echo "$YEAR$MONTH$DAY" 20181110 #> echo "$YEAR11$DAY" 10 #> echo "${YEAR}11$DAY" 20181110
The first echo
statement works as expected: The shell just concatenated the values of YEAR
, MONTH
, and DAY
to create a date in YYYYMMDD
format. The second echo
only prints 10
because this time the shell only sees two variables, namely $DAY
and $YEAR11
, which is undefined. To concatenate a combination of variables and constant strings, you must enclose the name of the variable in braces, as shown in the third echo
command.
You can make a variable point to another by combining quotes with exclamation marks:
#> MYNAME=Marco #> HISNAME=MYNAME #> echo "his name is $HISNAME" his name is MYNAME #> echo "his name is ${!HISNAME}" his name is Marco
Shell Expansion
The first thing the shell interpreter must do every time it parses a single whole line of a script is to expand it. Expansion consists of looking at each part of the line that is not a Bash built-in command to determine if and how it should be transformed into something else.
This procedure is needed because the actual content and structure of the current line might be different every time that line is parsed. The simplest example of this situation is a line using a variable that corresponds to the current time. In other words, the interpreter cannot know what to do with a line of script without fully expanding it first.
The Bash man page [3] says, "there are seven kinds of expansion performed, in this order: brace expansion, tilde expansion, parameter and variable expansion, command substitution, arithmetic expansion, word splitting, and pathname expansion."
This may seem messy, but you already saw most of these expansions: parameter and variable expansion, command substitution, word splitting with IFS
, pathname expansion, and tilde expansion with $HOME
and ~
.
Brace expansion lets you create sequences, or variations of strings with the least possible typing:
#> ATTENDEES= `echo 'Mr '{John,Frank,William}' Rogers'` #> echo $ATTENDEES Mr John Rogers Mr Frank Rogers Mr William Rogers
Another part of shell parsing that may be considered equivalent to expansions is the way backslashes are handled.
Escape characters (i.e., characters preceded by a backslash) have one of two special meanings. If they are alphabetic characters, they are "escape sequences" that tell the shell to perform some action. For example, \a
means "ring the alert bell," \n
means "go print to the next line,", and \t
means "print a horizontal tab."
If the backslash appears before other backslashes and quotes, it tells the shell just to print those characters, without interpreting them: If you type \\
, \'
, or \"
, the shell will just see and use a single backslash, a single quote, or a double quote, respectively.
Math with Variables
The Bash shell can use variables to do math. By no means is Bash the best tool to do this, but it can do enough things to spare you using another program when you need to do some quick calculations, perhaps as part of a bigger shell script. I will discuss shell math in a later installment, but initially I want to introduce one numeric shell variable, $RANDOM
, for two reasons. First, I want to show an example of arithmetic expansion. Second, $RANDOM
can be quite useful, even in scripts that are not about numbers. Listing 1 shows a small script using $RANDOM
taken from a web page [4] entirely devoted to this variable.
Listing 1
$RANDOM script
01 #! /bin/bash 02 FLOOR=70; 03 CEILING=230; 04 RANGE=$(($CEILING-$FLOOR+1)); 05 RESULT=$RANDOM 06 let "RESULT %= $RANGE"; 07 RESULT=$(($RESULT+$FLOOR)); 08 echo $RESULT
Every time you invoke it, $RANDOM
returns a random integer number between 0 and 32,767. The other variables $FLOOR
, $CEILING
, and $RANGE
"translate" that range to make $RESULT
a random number between 70 and 230. Lines 4, 6, and 7 show an initial partial example of how to perform math in Bash via arithmetic expansion.
« Previous 1 2 3 Next »
Buy this article as PDF
(incl. VAT)
Buy Linux Magazine
Subscribe to our Linux Newsletters
Find Linux and Open Source Jobs
Subscribe to our ADMIN Newsletters
Support Our Work
Linux Magazine content is made possible with support from readers like you. Please consider contributing when you’ve found an article to be beneficial.
News
-
Linux Servers Targeted by Akira Ransomware
A group of bad actors who have already extorted $42 million have their sights set on the Linux platform.
-
TUXEDO Computers Unveils Linux Laptop Featuring AMD Ryzen CPU
This latest release is the first laptop to include the new CPU from Ryzen and Linux preinstalled.
-
XZ Gets the All-Clear
The back door xz vulnerability has been officially reverted for Fedora 40 and versions 38 and 39 were never affected.
-
Canonical Collaborates with Qualcomm on New Venture
This new joint effort is geared toward bringing Ubuntu and Ubuntu Core to Qualcomm-powered devices.
-
Kodi 21.0 Open-Source Entertainment Hub Released
After a year of development, the award-winning Kodi cross-platform, media center software is now available with many new additions and improvements.
-
Linux Usage Increases in Two Key Areas
If market share is your thing, you'll be happy to know that Linux is on the rise in two areas that, if they keep climbing, could have serious meaning for Linux's future.
-
Vulnerability Discovered in xz Libraries
An urgent alert for Fedora 40 has been posted and users should pay attention.
-
Canonical Bumps LTS Support to 12 years
If you're worried that your Ubuntu LTS release won't be supported long enough to last, Canonical has a surprise for you in the form of 12 years of security coverage.
-
Fedora 40 Beta Released Soon
With the official release of Fedora 40 coming in April, it's almost time to download the beta and see what's new.
-
New Pentesting Distribution to Compete with Kali Linux
SnoopGod is now available for your testing needs