假设我有一个脚本,我在其中导出了一个变量,如下所示:
#!/bin/bash
foo(){
eval export one=1
}
foo1(){
eval export two=2
}
(foo)
foo1
echo "one=$one"
echo "two=$two"
但是我得到了以下输出:
root@centos1:~>/tmp/test.sh
one=
two=2
我无法看到 的价值$one
但可以看到 的原因可能是什么$two
?
答案1
全局变量从它们设置的那一刻起一直持续到它们被取消设置或过程结束的那一刻。全局(或局部)变量不会被不相关的子进程继承(如果子进程是一个 fork(子 shell),那么它会获得所有内容的副本 - 导出或非导出)。
全局导出变量类似于全局变量,但它们也会被子进程(甚至不相关的子进程)自动继承(作为进程环境的一部分)。 (通过导出,您可以将诸如 之类的变量传递CXXFLAGS
给诸如 之类的进程make
,该进程绝对不是您的 shell 的子 shell,并且make
生成的每个进程也将获得该变量。)
在您的示例中()
创建一个子 shell,它获取所有内容的副本。该foo
命令通过添加导出的变量来修改子 shell,然后子 shell 结束而不会使用导出的变量(没有孙子继承它)。现在,没有任何信息隐式地从子进程传输到父进程。孩子在他们的环境中所做的事情不会影响他们的父母。这就是您的变量one
未设置的原因。
顺便说一句,这些在这种情况下eval
是不必要的。eval
答案2
将命令括起来( )
将导致该命令位于子 shell 中。
如果要通过管道传输或退出,这可能很有用。
例如,以下命令
( date ; cmd1 ; cmd2 ) | grep ...
将导致连接前 3 个命令并将输出提供给grep
.
您可能会考虑{ }
,为此您应该参考 bash 的手册页(bash(1)
);这是摘录:
(list)
list
在子 shell 环境中执行(参见命令执行环境 以下)。影响 shell 环境的变量分配和内置命令在命令完成后不再有效。返回状态是退出状态list
。
{ list; }
list
只是在当前 shell 环境中执行。list
必须以换行符或分号终止。这被称为组命令。 返回状态是退出状态list
。请注意,与元字符不同(
和)
,{
和}
是保留字并且必须发生在 保留字 被允许被认可。由于它们不会导致断词,因此必须将它们与list
通过空格或其他 shell 元字符。
也可以看看shell 的控制和重定向运算符是什么?