在包含定义函数的命令的字符串上使用eval可以正常工作:
$ eval "p4() { echo 4; }"
$ p4
4
然而,当我这样做时它不再有效:
$ echo 'p3() { echo 3; }' | while read line ; do eval "$line"; done
$ p3
-bash: p3: command not found
为什么这不起作用?
答案 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
。