Next up is COMMAND SUBSTITUTION although there is a lot about
quoting is this section too. It is far too difficult to split
quoting away altogether, so instead I have elected to combine
both sections and include all the QUOTING information here too
where appropriate.
We have already seen the set of back-quotes
(or grave accents) in use in Script Example 1.1
and Example For Syntax
where the count variable was incremented. The
shell reads the command, or list of commands, or pipeline from
between the grave accents and executes them. The output from this
operation is then available to the shell for use in setting a
variable or echoing to the terminal. When the command string is
executed in this way, the output is stripped of newlines and blanks
are truncated to one space between words (unless preserved in
double-quotes). The grave accent example below shows several
different uses of the grave accent of varying complexity.
currentDir=`pwd`
lineCount=`wc -l $fileName | cut -c1-8`
thirdPath=`echo $PATH | cut -f3-3 -d:`
lastWord=`head -$lineCount $fileName | tail -1 | tr '''/' | basename`
In order, these commands and pipelines are all used to set some
variable values.
- First is getting the current directory using the pwd
command, the simplest usage. Just execute the command and use
the output to set the variable.
- Next is getting the count of lines in a file. Use the wc
command (word count) with the -l flag (lines) then pipe
this to the cut command and use the -c flag (characters)
to cut out the 1st to 8th character (the number) from the
output. Use this to set the variable. The cut is required
because wc insists on including the filename in
the output string. Also beware of the number part, as it
is not an integer but a string of numbers. If you
want a number, then use the expr command to add a zero
to the result which has the effect of converting the type. Although
I said earlier that shell variables are un-typed, the test
command gets upset when presented with a string and is then told
to evaluate it as greater or less-than another number. The variables
maybe typeless, however their contents are typed unless converted.
- Next is getting the third string from a complex string list.
The PATH environment variable
(See - Startup & Environment)
is a list of search paths for the UNIX system
to use when searching for command locations within the directory
structure. Each path is separated from its neighbour by a colon
thus: [/bin:/usr/bin:/usr/lib:/usr/etc]. This command pipeline
echoes the path string into cut using the -f flag
(field) to select the third field. The -d flag specifies
the delimiter character for the fields as a colon in this
case. Once again the result of the executed pipeline is used to
set a variable.
- Lastly finding the last word on a particular line. Use the
head command with the line_count variable to echo
out the top line_count lines of a file. Pipe this through
the tail command and only pass the last one line. Having
got the line you want, pipe this through tr (transform)
and change each blank into a forward-slash
(a UNIX directory separator). Then pipe this through basename
which always strips away the full path leaving just the filename.
This leaves you with just the last word, however long the line
was, and however many words there were on the line, which can
then be used to set our variable.
The difference between the single and double quote are also useful
to know. The single quote is what you use to enclose a literal
string. Whatever is between single quotes
remains unchanged by the shell. If you enclose something in double
quotes then concatenated blanks are preserved
(as in the literal case with the single quotes) but variables
are substituted by their values and filenames are expanded from
their wild-cards to full filenames and or paths. The best way
to see this is in the example below.
my_name="Fred Smith" # Set a variable
echo "$my_name" # Will output - Fred Smith
echo '$my_name' # Will output - $my_name
This may give the impression that the single quote is not much
use. However, if you want to echo a dollar sign out to another
script file for later execution, it can be very handy. See below.
echo "echo \"'$my_name'\"" > $file_name
Here the echo statement is creating another echo
statement in an output file for later use. The $my_name
variable is hidden inside the single-quotes and so will
be passed as a literal string to the output file. Another feature
shown here is the back-slash which is used as an escape
signal for the shell. It tells the shell not to read the next
character, but just pass it on. In this way the double-quote
also makes it to the output file unscathed. The backslash can
be used to escape any character that is special to
the shell - even a newline. This allows you to create very long
lines (See - Functions).
To pass a back-slash use a double back-slash.
As noted earlier, the key character here is the dollar symbol
($) which instructs the shell to substitute the value where the
parameter name (or variable) is located. There is a touch more
flexibility here than at first appears however. There are in fact
5 different ways that the shell can substitute the value depending
on the syntax used.
- ${name} The value, if any, is substituted. The braces are
only required if name is followed by characters which
are not to be interpreted as part of the name string. For
instance, you might always use a temporary file name which is
generated from the running script using the form "${0}.tmp" which
creates a file name of "script.tmp".
- ${name:-word} The value, if any, is substituted. If the value
is NULL, substitute word instead. Word can be
a literal string, another parameter or a substituted command
string output. Can be used to substitute a positional parameter
($digit).
- ${name:=word} As above but cannot be used to substitute a
positional parameter.
- ${name:?word} If name is set and is not NULL, substitute
its value. Else output word and exit from shell. If
word is missing, the message 'parameter null or not set'
is output. This can be a useful debugging aid.
- ${name+word} If name is set and is not NULL, substitute
word. Else substitute nothing. This means the parameter
is always substituted by word unless parameter is null, in
which case it remains null.
|