我有下面的 shell 脚本
var="this is a test"
ls -ltr| while read file
do
echo $var
done
echo $var
我得到以下输出:
this is a test
this is a test
this is a test
由于管道将生成一个新的子 shell,并且我也不在主 shell 中导出我的“var”变量,因此如何在 while 循环内将变量“var”的值设置为“这是一个测试”?
据我所知,为了让子 shell 从父 shell 继承变量值,我们需要导出变量,但在这种情况下,变量值是在没有“export”语句的情况下继承的。
答案1
让我们看看 Bash 手册怎么说(3.7.3 命令执行环境)
shell有一个执行环境,它由以下部分组成:
- 通过变量赋值设置的 shell 参数或设置或从环境中的 shell 父级继承
- 在执行期间定义的 shell 函数或从环境中的 shell 父级继承的 shell 函数
命令替换、用括号分组的命令以及异步命令在 a 中调用子 shell 环境是 shell 环境的副本[...]
对子 shell 环境所做的更改不会影响 shell 的执行环境。
在3.2.2 管道,也有说
管道中的每个命令都在其自己的子 shell 中执行
(当然这只适用于多命令管道)
因此,管道的各个部分以及其他子 shell 都会获取以下副本全部shell 变量,但对它们的任何更改都是不是对外壳可见。
对于其他命令,您仍然需要export
:
当要执行除内置函数或 shell 函数之外的简单命令时,将在由以下内容组成的单独执行环境中调用它。
- 标记为导出的 shell 变量和函数,以及为命令导出的变量,在环境中传递
深思:这打印了什么?
bash -c 'f() { echo "$a $b"; }; a=1; b=1; (b=2; f); f'