Article
9.16
introduces command substitution with a pair of backquotes (
``
). Let's review. The shell runs a backquoted string as a command, then replaces the string with its output. Sometimes - though not as often - you'll want to use the results from one backquoted string as arguments to another command, itself also inside backquotes. To do that, you need to nest the backquotes, to tell the shell which command (which set of backquotes) should be done first, with its output given to the second command. This is tricky with backquotes; the Korn Shell introduced an easier way that you'll see below. Here's a simple example - the first command line uses nested backquotes, and the next two commands show its parts: [5]
[5] True, this won't give the right answer after 1998. True, the Korn shell has built-in arithmetic. But this is a simple example!
$echo "Next year will be 19`expr \`date +%y\` + 1`."
Next year will be 1997. $date +%y
96 $expr 96 + 1
97
The command to run first has escaped backquotes (
\`\`
) around it. In the example above, that's the
date +%y
command.
date +%y
outputs the year - in this case,
96
- and that value is passed to the
expr
command.
expr
adds 96 and 1 to get 97. Then that result (from the outer backquotes) is passed to
echo
, on its command line, and
echo
prints the message.
Why does the inner command, inside the escaped backquotes (
\`\`
), run first? It's because the backslash before the backquote
turns off the special meaning (
8.14
)
of the backquote. So, when the shell first
evaluates the command line (
8.5
)
, which backquotes does it see? It sees the unescaped backquotes, the ones around the
expr
command, and the shell runs the command:
expr `date +%y` + 1
But when the shell evaluates that command line, it sees the backquotes in it (now unescaped) and runs
that
command-
date +%y
. The
date +%y
command outputs
96
. Next, the shell can finish the command
expr 96 + 1
. It outputs 97. Then the
echo
command can print its message.
Whew. If you use the Korn shell or
bash
, there's an easier way: the
$(
command
)
operators. Use
$(
before the command, where you would use an opening backquote. Put the
)
after the command, in place of a closing backquote. You don't have to escape these operators when you nest them.
Here's the previous example with
$( )
, then a more real-life example:
2>&1 |
$ |
---|
The inner command - in this case, the find ( 17.1 ) -is run first. Its output, a list of filenames, is put on the command line of the tar ( 20.1 ) command. Finally, the output of tar (in this case, an error message) is stored in the tarout shell variable.
Beginners (and some long-time programmers too) might argue that you should never nest command substitution because it's too confusing. I think there are times nesting is clearer. It's more compact and doesn't need temporary storage. And it's not that hard to understand once you see what's happening. There's another nice example in article 38.13 .
-