If you read the previous article ( 8.9 ) , you saw that, 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 ( 1.5 ) :
%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
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 $output
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. There are more examples of eval in articles 5.4 , 10.7 , 10.10 , 45.17 , 45.34 , 46.3 , and others.
-