Assessment of variables in a row

The last line in this script will not work as I expect:

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

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

+8
bash
source share
4 answers

Take it step by step:

When you do this:

 mycmd='cat $myfile' 

You prevent shell interpolation of $myfile . Thus:

 $ echo $mycmd cat $myfile 

If you want to enable 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 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 evaluate $mycmd in an echo expression when you echo it:

 $ echo $(eval "echo $mycmd") $ cat afile.txt $ myfile=bfile.txt $ echo $(eval "echo $mycmd") cat bfile.txt 
+26
source share

You can write:

 eval echo eval $mycmd 

or a little more reliable:

 eval echo eval "$mycmd" 

However, I recommend avoiding eval whenever possible; it tends to be very fragile because there are many complicated steps in processing the command line bash, and using eval usually means that you will complete these steps more than once. It’s hard to keep track of what is really happening.

+7
source share

You need to determine the echo, and not vice versa:

 eval echo "eval $mycmd" 

or

 eval echo eval "$mycmd" 

I think the former is preferable, but at least it quotes the extension of the variable.

+1
source share

If you are using bash, the best way to do this is to use arrays:

 myfile="afile.txt" mycmd=(cat "$myfile") echo "${mycmd[@]}" "${mycmd[@]}" 
+1
source share

All Articles