What is eval?

eval is a built-in command in most Unix-like operating systems, such as Linux. It comes from the sh (Bourne shell) programming language, which was one of the original Unix shells. The eval command is included in all POSIX-compliant shells, which means it’s available in modern shells like bash, zsh, and others.

KEY idea:The purpose of eval is to take its arguments, concatenate them into a single command, and then execute that command. In other words, it is used to construct and execute command lines dynamically.

The existence of eval is due to the need for more dynamic shell scripting. Sometimes, it is useful to construct a command line piece-by-piece, based on conditions that aren’t known until the script is run. eval enables this kind of dynamic scripting.

Use Case 1: Dynamically Setting Variable Names

for i in 1 2 3
do
  eval  VAR$i=$i
done

echo $VAR1  # Outputs 1
echo $VAR2  # Outputs 2
echo $VAR3  # Outputs 3

In this script, eval is used to dynamically create the variable names VAR1, VAR2, and VAR3, each containing the corresponding value. Without the eval keyword, the shell would not be able to evaluate, ie substitute, the $i variable with 1, 2 and 3.

Use Case 2: Executing a Command Stored in a String

command="ls -l"
eval $command

Here, eval is used to execute a command that was stored in a string. This can be helpful in cases where the command to be executed is generated dynamically.

Use Case 3: Handling Indirect References

a='hello'
b='a'
eval echo \$$b  # Outputs 'hello'

In this example, eval is used to print the value of a variable when the name of the variable is stored in another variable.

How would these use cases be implemented if eval did not exist?

You can replicate some of the functionality of eval using other commands or features of the shell, although it may be more complex or less efficient. Here are examples corresponding to the previous use cases, done without using eval:

Use Case 1: Dynamically Setting Variable Names

Bash 4.3 introduced “namerefs” or “reference variables” which can be used for indirection:

for i in 1 2 3
do
   declare VAR$i=$i
   declare -n ref=VAR$i
   echo ${ref}
done

Use Case 2: Executing a Command Stored in a String

The preferred way to store and execute commands isn’t with a plain string, but with a function or an array. However, if you have a string, you can use the bash -c command:

command="ls -l"
bash -c "$command"

Use Case 3: Handling Indirect References

Bash provides a feature called “variable indirection” which allows you to access the value of a variable whose name is stored in another variable:

a='hello'
b='a'
indirect="${!b}"
echo "$indirect"  # Outputs 'hello'