28.14. Command Substitution
A pair of backquotes
(``) does command substitution. This is really
useful -- it lets you use the standard output from one command as
arguments to another command.
Here's an example. Assume you want to edit all files
in the current directory that contain the word
"error." Type this:
-l Section 33.6
$ vi `grep -l error *.c`
3 files to edit
"bar.c" 254 lines, 28338 characters
...
$
But why does this work? How did we build the incantation above?
First, think about how you'd do this without using
any special techniques. You'd use
grep to find out which commands contain
the word
"error"; then
you'd use vi to edit this list:
$ grep error *.c
bar.c: error("input too long");
bar.c: error("input too long");
baz.c: error("data formatted incorrectly");
foo.c: error("can't divide by zero"):
foo.c: error("insufficient memory"):
$ vi bar.c baz.c foo.c
Is there any way to compress these into one command? Yes, by using
command substitution. First, we need to modify our
grep command so that it produces only a list of
filenames, rather than filenames and text. That's
easy; use grep -l:
$ grep -l error *.c
bar.c
baz.c
foo.c
The -l option
lists each filename only once, even if many lines in the file match.
(This makes me think that grep -l was designed
with precisely this application in mind.) Now, we want to edit these
files; so we put the grep command inside
backquotes, and
use it as the argument to vi:
$ vi `grep -l error *.c`
3 files to edit
"bar.c" 254 lines, 28338 characters
...
$
You might be wondering about the difference between the
"vertical" output from
grep and the
"horizontal" way that people
usually type arguments on a command line. The shell handles this with
no problems. Inside backquotes, both a newline and a space are
argument separators.
The list you use with command substitution doesn't
have to be filenames. Let's see how to send a
mail message (Section 1.21) to all the users logged on to the system now.
You want a command line like this:
% mail joe lisa franka mondo bozo harpo ...
Getting there takes a little thinking about what Unix commands you
need to run to get the output you want. (This is real
"Power Tools" stuff!) To get a list
of those users, you could use who
(Section 2.8). The who output also lists
login time and other information -- but you can cut that off with
a command like cut
(Section 21.14):
% who | cut -c1-8
joe
lisa
franka
lisa
joe
mondo
joe
...
Some users are logged on more than once. To get a unique list, use
sort -u (Section 22.6). You're done. Just put the
name-making command line between backquotes:
% mail `who | cut -c1-8 | sort -u`
If you aren't sure how this works, replace the
command you want to run with echo
(Section 26.5):
% echo `who | cut -c1-8 | sort -u`
bozo franka harpo joe lisa mondo
After using Unix for a while, you'll find that this
is one of its most useful features. You'll find many
situations where you use one command to generate a list of words,
then put that command in backquotes and use it as an argument to
something else. Sometimes you'll want to nest
(Section 36.24) the backquotes -- this is where the
bash, ksh,
bash, and zsh $(
) operators
(which replace the opening and closing backquote, respectively) come
in handy. There are some problems with command substitution, but you
usually won't run into them.
This book has many, many examples of command substitution. Here are some of
them: making unique filenames (Section 8.17), removing some files
from a list (Section 14.18), setting your shell prompt (Section 4.6, Section 4.8, Section 4.14), and setting
variables (Section 4.8, Section 36.23).
-- JP
 |  |  | 28.13. Here Document Example #1: Unformatted Form Letters |  | 28.15. Handling Lots of Text with Temporary Files |
Copyright © 2003 O'Reilly & Associates. All rights reserved.
|