Expansions.
From our previous discussion on wildcards, we know a little bit about expansions. For example, the *
character expands to include all characters present. This expansion occurs before any shell command is executed hence the shell would not see the *
only its expanded characters. This is true for most wildcards as William Schotts explains in this article. The problem of how to print these character wildcards is by using escape character sequences. The \
, '
- which treats all characters within it as non-special and "
which suppresses all special meanings of characters except $
,\
and `
.
Brace expansions.
Brace expansions are special in that they expand to each term in the brace. ranges can also be used in braces as we'll see in the examples and as William Schotts explains.
Shell Variables.
The shell gives the ability to create and use variables. Variables could be described as special containers that hold given values. Variable names can be used to access and manipulate that variable content.
Alias.
The alias feature, allows one to create an alias of a given command. If you commonly mistype a command, the alias feature can be truly helpful. Aliases can be removed as explained here.
Some example applications of the above concepts.
To create an alias of
ls
asrm *
:alias ls="rm *"
. This is straightforward as the command is given a value and it is set.A command that prints hello user, where user is the current Linux user, you'll have to use the
USER
environment variable that keeps track of the current user. The$
will give that variable. The echo command will have to use"
since the variable has to be expanded. the full command would then be:echo "hello $USER"
.To add
/action
to thePATH
, you have to reset the path variable with the new path. Variables are set by stating their names and giving them a value. However, this goal requires an addition, not a reset. Therefore, the path variable has to be expanded to its initial one and the extra location added. Now the PATH variable consists of several locations that store the path to executables including commands. To add a path, the full path should be spelled out and the/action
added to it separated by a colon. In this case, the path is stored in an existing variable that can be accessed using the $ sign. hence the command becomes:PATH = $PATH:/action
.To list environment variables, use
printenv
.To list local variables, environment variables and functions, use
set
.To create a variable, give the variable name, equal sign then the value without spaces. i.e. to create a local variable called recuse with the value nox;
recuse=nox
.To create a global variable use the
export
keyword. e.g. to create a global variable with the values in 6;export recuse=nox
.To print the result of the addition of 128 with the value stored in the environment variable
TRUEKNOWLEDGE
, followed by a new line:echo $((($TRUEKNOWLEDGE) + 128))
. This code works by using the$
to display the result and the second to evaluate theTRUEKNOWLEDGE
as a variable.The division works similarly. e.g. To print the result of
POWER
divided byDIVIDE
, followed by a new line where both are environment variables;echo $(($POWER / $DIVIDE))
.Converting to various bases in the shell is still an arithmetic operation. The shell will execute it similarly to other arithmetic operations i.e.
$((expression)).
The syntax for converting is,$((base#numbertoconvert))
. To convert 85 to base 16,$((16#85))
To convert a number stored in a variable, use the$
to tell bash to convert it to a number. To convert a number stored inBINARY
to base 2 and display it,echo $((2#$BINARY))
.The next example is an interesting application of brace expansions. The task is to print all possible combinations of two letters, using the English alphabet, except
oo.
This calls for printing all the letters, then piping them before printing to a command that will removeoo
. Using brace expansions to get all possible combinations is fairly easy,echo {a..z}{a..z}
. Of course, the quickest command to remove a given pattern isgrep
. This will happen when it is used with the-v
option. Of course,grep
displays a pattern. However, piping it directly togrep
won't work sincegrep
checks a pattern following a newline. The echo printing will put all its output in one line. The way to combat this is by converting the space between the letters in the output to a newline character usingtr
. The full command will therefore be:echo {a..z}{a..z} | tr ' ' '\n' | grep -v oo
.This example looks at printing decimals (floats) to the output. The
printf
function provides an extremely simple and easy way to do this. It works similarly ( not the same) to theprintf
function found in the C programming language (runman printf
to learn more). The way to print something usingprintf
, in the shell (BASH shell), is by providing the string (characters) and when you wish to pass a variable, put the`%`
before the conversion specifier, a letter stating the variable type. With float variables, the specifier is the letter f and the number of decimal places to use can be placed using a.
after the%
and the number of decimal places before usingf
. i.e. to print 4 decimal places%.4f
. To print a number stored inNUM
with two decimal places, followed by a new line;printf ".2f\n" $NUM
.The next example is tricky since it looks at custom bases. The task reads;
Write a shell script that adds the two numbers stored in the environment variables
WATER
andSTIR
and prints the result.WATER
is in basewater
STIR
is in basestir.
The result should be in base
bestchol
This is particularly challenging since the bases are not common numbers. The base water has 5 digits hence it can be translated to base 5 while stir has 4 hence it can be translated to base 4. First, water will be translated into digits and the result cast into each. Using printf and casting the bases:
printf '%o\n' $(( 5#$( echo $WATER | tr water 01234) + 5#$( echo $STIR | tr stir. 01234 ) )) | tr 01234567 bestchol
.
These examples should give you a good introduction to shell variables and expansions. Have fun practicing.