With all the different substitution mechanisms available in the C shell, it's important to know which take precedence. Here's the order in which the C shell interprets the command line:
History substitution
Splitting words (including special characters)
Updating the history list
Interpreting single quotes ('
) and double quotes ("
)
Alias substitution
Redirection of input and output ( e.g., >
, <
, and |
)
Variable substitution
Command substitution
Filename expansion
(The Bourne shell is essentially the same, except that it doesn't perform history substitution or alias substitution.)
History substitutions are always done first. That's
why quotes won't protect a !
from the shell; the shell sees the
exclamation point and substitutes a command from the history before
it's even thought about the quotation marks.
To prevent history substitution, you need to
use a backslash (8.15).
Let's work through a simple command line that uses several of these features. Nothing in this command line will be difficult, but it will give you a feeling for what we mean by saying that "the shell performs variable substitution after alias substitution." Here's the command line; it has both space and TAB characters:
%ls -l $HOME/* | grep "Mar 7"
And here's what happens:
There are no history operators, so history substitution (11.2) doesn't happen. (The Bourne shell wouldn't perform this step.)
The command line is split into separate "words" at the whitespace characters.
The words are ls
, -l
,
$HOME/*
, |
, grep
, and "Mar 7"
.
The shell ignores the amount of whitespace (spaces and TABs)
between different words
in a command line.
Any unquoted whitespace creates a new word.
The shell doesn't do anything special with options (like -l
).
Options are passed to the command being run, just like any other word;
[2]
the command decides how to interpret them.
Also, note
that
quotes (8.14)
prevent the shell from splitting "Mar 7"
into two words
or eating the two spaces - even though quote interpretation comes later.
[3]
At this point, the
command line looks like this:
[2] The convention of starting options with a dash (
-
) is just that: a convention. Although option handling is being standardized (44.18), each command can interpret its options any way it wants to.[3] In an ls -l listing, dates less than 10 have two spaces before them (they're printed in a field 2 characters wide).
ls -l $HOME/* | grep "Mar 7"
The shell sticks the command line onto the history list. The Bourne shell wouldn't perform this step, either.
The shell recognizes the double quotes around "Mar 7"
and notes that
wildcard expansion (yet to come) shouldn't take place inside the quotes.
The shell checks whether or not ls
or grep
are
aliases (10.2).
They could be, but we're assuming they aren't.
The shell notices the |
, and does
whatever's required (13.1)
to set up a
pipeline.
The shell notices the
environment variable (6.1)
$HOME
,
and replaces this
variable with its value (/home/mikel
).
At this point, the
command line looks like:
ls -l /home/mikel/* | grep "Mar 7"
The shell looks for backquotes (9.16), executes any command inside the backquotes, and inserts its output on the command line. In this case, there's nothing to do. (If there are wildcards or variables inside the backquotes, they aren't interpreted before the shell runs the command inside the backquotes.)
The shell looks for
wildcards (1.16).
In this case, it sees the *
and
expands the filename accordingly, leaving something like this:
ls -l /home/mikel/ax ... /home/mikel/zip | grep "Mar 7"
The shell executes the ls command, executes the grep command, with the aforementioned pipe sending the ls output into grep's input.
One character you'll see often on command lines is ;
(semicolon).
It's used as a command separator:
type one complete command line - then, instead of pressing RETURN, type
a semicolon and another complete command line.
Chaining commands with semicolons is especially useful in
subshells (13.7),
aliases,
and
lists (13.8)-
this book has lots of examples - in articles
40.2
and
10.2,
for instance.
There's more about command-line interpretation in the articles on
wildcards inside aliases (8.9),
eval (8.10),
conditional execution (44.9),
and many others.
[For some nitty-gritty details about the C shell that are fun, too,
I recommend Chris Torek's article
8.12.
-JP ]
-
,