在子shell环境中执行命令时会发生这种情况:
该命令将在当前shell execution environment
“影响shell环境的变量赋值和内置命令在命令完成后不会保持有效” (quote)
示例:
#!/bin/sh
export TOTO=123
FOO=abc
(mycmd)
在这种情况下,mycmd将能够读取TOTO但不能读取FOO,并且mycmd实现的这两个变量值的每个更改都不会在当前shell中显示。
但是当我们用函数做同样的事情时会发生什么?
示例:
#!/bin/sh
export TOTO=123
FOO=abc
function (){
echo $TOTO
echo $FOO
TOTO=${TOTO}456
FOO=${FOO}def
}
(function)
echo $TOTO
echo $FOO
结果:
123
abc
123
abc
合理地,在子shell中执行的函数不能改变父shell中定义的变量的内容,另一方面,它能够不加选择地读取所有变量,即使它们没有被导出。
有人可以用更好的方式解释这种行为吗? 一些参考文献的链接将非常受欢迎,因为我找不到任何关于它的信息。
答案 0 :(得分:2)
您所观察到的与功能无关。子shell获得所有环境,甚至是未导出的变量。为了说明,我们定义两个变量:
$ alpha=123
$ export beta=456
观察子shell可以同时访问:
$ (echo $alpha $beta)
123 456
但是,如果我们开始一个新流程,它只会看到导出的变量:
$ bash -c 'echo $alpha $beta'
456
man bash
记录子壳如下:
(list)
list在子shell环境中执行(参见COMMAND 下面的执行环境)。变量赋值和内置 影响shell环境的命令不会保持有效 命令完成后返回状态是退出状态 列表。
如果我们查看" COMMAND EXECUTION ENVIRONMENT",我们发现它包含
由变量赋值设置的shell参数,或者是从环境中的shell父级设置或继承的shell参数。
换句话说,它包含变量是否已导出。
如果我们进一步阅读,我们发现这与"一个简单的命令形成对比,而不是内置函数或shell函数。"这些命令只接收导出的变量。
答案 1 :(得分:1)
这是一个简短的答案,希望能够解释这些差异。它有两个函数myfun
和myfunlocal
。在myfunlocal
中,toto
和foo
都声明拥有local
和toto
的{{1}}个副本,这些副本在功能中更新时不会反映回来在脚本的主体中,虽然foo
没有进行myfun
重新声明,因此对local
和toto
的更改会反映在主体中。但是,如果在子shell中运行foo
,则(myfun)
和toto
的更改不会反映在脚本的foo
正文中:
main
<强>输出强>
#!/bin/bash
function myfun {
printf "\n myfun - toto : %-6s foo : %s\n" \
"$toto" "$foo"
toto=lizard
foo=456
printf " myfun - toto : %-6s foo : %s\n" \
"$toto" "$foo"
}
function myfunlocal {
printf "\n myfunlocal - toto : %-6s foo : %s\n" \
"$toto" "$foo"
local toto=lizard
local foo=456
printf " myfunlocal - toto : %-6s foo : %s\n" \
"$toto" "$foo"
}
toto=dog
foo=123
printf "\n before myfunlocal : toto : %-6s foo : %s\n" "$toto" "$foo"
myfunlocal
printf "\n after myfunlocal : toto : %-6s foo : %s\n" "$toto" "$foo"
(myfun)
printf "\n after subshell myfun: toto : %-6s foo : %s\n" "$toto" "$foo"
myfun
printf "\n after simple myfun : toto : %-6s foo : %s\n\n" "$toto" "$foo"