2016-04-28 11 views
1

Mit eval auf eine Zeichenfolge, die einen Befehl enthält, der eine Funktion ohne Probleme funktioniert definiert:Warum funktioniert `eval` nicht in meiner Schleife?

$ eval "p4() { echo 4; }" 
$ p4 
4 

Allerdings, wenn ich es so tun, es funktioniert nicht mehr:

$ echo 'p3() { echo 3; }' | while read line ; do eval "$line"; done 
$ p3 
-bash: p3: command not found 

Warum funktioniert diese Arbeit?

+0

Ich bin mir nicht sicher, ob du mit 'eval' herumspielen solltest, wenn du noch keine Subshells verstehst. – chepner

Antwort

8

Es geschieht aufgrund einer Sub-Shell, die aufgrund Ihrer Pipeline nach echo erzeugt wird. Das erklärt Funktion p3 in Sub-Shell, nicht von der aktuellen (Parent) Shell zugänglich.

Sie können es vermeiden, indem Heredoc statt Pipeline mit:

while read line ; do eval "$line"; done <<< 'p3() { echo 3; }' 

p3 
3 
3

Von man bash:

Jeder Befehl in einer Pipeline wird als separater Prozess (dh ausgeführt, in einer Subshell).

Da Variablen nicht in die Subshell übertragen werden, ist p3 dort nicht zugänglich.

Nebenbei: zsh führt das zweite Beispiel genau so aus, wie Sie erwartet haben, dh es gibt 3 aus.

4

Was anubhava sagt, ist korrekt und Sie sollten immer daran denken. Lassen Sie mich nur eine Alternative vorschlagen: Sie Prozess Substitution verwenden und source:

source <(echo 'p3() { echo 3; }') 
p3 

Die Frage ist, warum wollen Sie das tun?

Verwandte Themen