Unix Power Tools
eval: When You Need Another Chance
by Mike Loukides
02/10/2000
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:
The shell converts $b into $a; then eval runs through the
command-line evaluation process again, converting echo $a
into echo foo - 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:
...
command='grep $grepopts $searchstring $file'
for opt
do
case "$opt" in
file) output=' > $ofile' ;;
read) output=' | more' ;;
sort) postproc=' | sort $sortopts';;
esac
done
...
eval $command $postproc $outputDo 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.
More Unix Power Tools