2013-08-13 20 views
8

L'ultima riga in questo script non funziona come mi aspetto:Valutare le variabili in una stringa

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

Qui risuonano stampe 'eval cat $ myfile'. Come posso stampare 'eval cat afile.txt'?

risposta

26

Prendiamo le cose passo dopo passo:

Quando si esegue questa operazione:

mycmd='cat $myfile' 

Si impedisce alla shell di interpolare $myfile. Così:

$ echo $mycmd 
cat $myfile 

Se si desidera consentire l'interpolazione, è possibile utilizzare le virgolette doppie:

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

Questo, naturalmente, si blocca l'interpretazione di $mycmd quando si fa un 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 

confrontare questo a:

$ 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 

Quello che probabilmente vuole fare è quello di valutare l'$mycmd in un enunciato echo quando si echo è:

$ echo $(eval "echo $mycmd") 
$ cat afile.txt 
$ myfile=bfile.txt 
$ echo $(eval "echo $mycmd") 
cat bfile.txt 
+0

Questo non funziona per : grep fatal 'find/var/log/-name 'current' – taco

1

È necessario eval l'eco, piuttosto che il contrario:

eval echo "eval $mycmd" 

o

eval echo eval "$mycmd" 

penso che il primo è preferibile, ma almeno citare l'espansione variabile.

7

Si può scrivere:

eval echo eval $mycmd 

o un po 'più robusto:

eval echo eval "$mycmd" 

Detto questo, io consiglierei di evitare eval quando possibile; tende ad essere molto fragile, perché ci sono molti passaggi complicati nell'elaborazione della riga di comando di Bash e l'uso di eval significa in genere che eseguirai questi passaggi più di una volta. È difficile tenere traccia di ciò che sta realmente accadendo.

1

Se stai usando bash, il modo migliore per farlo è quello di utilizzare le matrici:

myfile="afile.txt" 
mycmd=(cat "$myfile") 
echo "${mycmd[@]}" 
"${mycmd[@]}" 
Problemi correlati