Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Evaluating variables in a string

Tags:

The last line in this script won't work as I expect:

myfile="afile.txt" mycmd='cat $myfile' eval $mycmd echo eval $mycmd 

Here echo prints 'eval cat $myfile'. How can I print 'eval cat afile.txt'?

like image 581
Robert Kubrick Avatar asked Aug 13 '13 21:08

Robert Kubrick


People also ask

How do you evaluate a string in bash?

Assign strings to variables c, a1, and a2. Then, use eval to evaluate those arguments and join them into a single string, with a space between each. Then, run that string as a command, "echo Hello, World!".

What is command substitution in bash?

Command substitution is a mechanism that is followed by programmers in a bash script. In this mechanism, the output of a command replaces the command itself. Bash operates the expansion by executing a command and then replacing the command substitution with the standard output of the command.


2 Answers

Let's take things step by step:

When you do this:

mycmd='cat $myfile' 

You prevent the shell from interpolating $myfile. Thus:

$ echo $mycmd cat $myfile 

If you want to allow the interpolation, you can use double quotes:

$ mycmd="echo $myfile"  #Double quotes! $ echo "$mycmd" cat afile.txt 

This, of course, freezes the interpretation of $mycmd when you do an eval.

$ myfile="afile.txt" $ mycmd="echo $myfile" $ echo $mycmd cat afile.txt $ eval $mycmd   #Prints out afile.txt $ myfile=bfile.txt $ eval $mycmd   #Still prints out afile.txt and not bfile.txt 

Compare this to:

$ myfile="afile.txt" $ mycmd='cat $myfile'   #Single quotes hide $myfile from the shell echo $mycmd cat $myfile             #Shell didn't change "$myfile", so it prints as a literal $ eval $mycmd           #Prints out afile.txt $ myfile=bfile.txt $ eval $mycmd           #Now prints out bfile.txt 

What you probably want to do is to evaluate the $mycmd in an echo statement when you echo it:

$ echo $(eval "echo $mycmd") $ cat afile.txt $ myfile=bfile.txt $ echo $(eval "echo $mycmd") cat bfile.txt 
like image 79
David W. Avatar answered Sep 22 '22 03:09

David W.


You can write:

eval echo eval $mycmd 

or a bit more robust:

eval echo eval "$mycmd" 

That said, I'd recommend avoiding eval whenever possible; it tends to be very fragile, because there are many complicated steps in Bash command-line processing, and use of eval typically means you will perform those steps more than once. It's hard to keep track of what's really going on.

like image 20
ruakh Avatar answered Sep 23 '22 03:09

ruakh