为什么`eval`不在我的循环中工作?

时间:2016-04-28 18:59:20

标签: bash

在包含定义函数的命令的字符串上使用eval可以正常工作:

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

然而,当我这样做时它不再有效:

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

为什么这不起作用?

3 个答案:

答案 0 :(得分:8)

由于在echo之后由于您的管道而产生了子shell,因此发生了这种情况。这是在子shell中声明函数p3,无法从当前(父)shell访问。

您可以使用here-string而不是管道来避免它:

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

p3
3

答案 1 :(得分:4)

anubhava所说的是正确的,你应该始终牢记这一点。我只想提出一个替代方案:您可以使用流程替换和source

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

问题是,你为什么要这样做?

答案 2 :(得分:3)

来自man bash

  

管道中的每个命令都作为一个单独的进程执行(即在子shell中)。

由于变量未转移到子shell,p3无法在那里访问。

顺便说一句:zsh完全按照预期的方式执行第二个示例,即输出3