Unix Power Tools
eval: When You Need Another Chance

Most of the time, the
shell evaluates the command line "in the right order." But what about
when it doesn't? Here's a situation that the shell can't handle.
It's admittedly contrived, but not too different from what you might
find in a shell program:

% set b=\$a
% set a=foo
% echo $b
$a

When we use the variable $b, we'd like to get the variable
$a, read it, and use its value. But that doesn't happen.
Variable substitution happens once, and it isn't recursive. The value
of $b is $a, and that's it. You don't go any further.

But there's a loophole. The eval command says, in essence,
"Give me another chance. Re-evaluate this line and execute it."
Here's what happens if we stick eval before the echo:

% eval echo $b
foo

The shell converts $b into $a; then eval runs through the
command-line evaluation process again, converting echo$a
into echofoo - which is what we wanted in the first place!

Here's a more realistic example; you see code like this fairly often
in Bourne shell scripts:

Do you see what's happening? We're constructing a command that will
look something like:

grep $grepopts $searchstring $file | sort $sortopts > $ofile

But the entire command is "hidden" in shell variables, including the
I/O redirectors and various options. If the eval isn't there,
this command will blow up in all sorts of bizarre ways. You'll see
messages like | not found, because variable expansion occurs after
output redirection. The "nested" variables (like $ofile, which is
used inside of $output) won't be expanded either, so you'll also see
$ofile not found.
Putting an eval in front of the command forces the shell to
process the line again, guaranteeing that the variables will be
expanded properly and that I/O redirection will take place.

eval is incredibly useful if you have shell variables that
include other shell variables, shell variables that include aliases,
shell variables that include I/O redirectors,
or all sorts of perversities. It's commonly used within shell
scripts to "evaluate" commands that are built during execution.