4

最近我一直在阅读高级 Bash 脚本,我发现一些关于父壳和子壳之间的变量范围的事情让我很困惑。这里是:

场景:有一些方法可以生成子外壳:首先,(command-lists); 其次,执行非内置命令或脚本,以此类推。

由于当我们在父脚本中运行脚本时,子脚本无法看到父 shell 中的变量。为什么在(command-lists)结构中子shell可以看到父shell中的变量。例如

  1. (命令列表)

    $ a=100
    $ (echo $a)
    100
    $
    
  2. 运行脚本

    $ cat b.sh
    echo $a
    $ a=100
    $ ./b.sh
    # empty
    

如何?

4

1 回答 1

8

如果您在原始脚本中运行子外壳程序:

(command1; command2; ...)

子 shell 是由 创建的原始 shell 的直接副本fork(),因此可以直接访问它自己的所有可用原始变量的副本。

假设子 shell 中的命令(等)本身就是 shell 脚本command1command2这些命令由子shell调用执行fork(),然后exec()创建一个新的shell,新的shell不会继承原始shell的非导出变量。


直接解决您的示例:

$ a=100
$ (echo $a)
100
$

在这里,子 shell 拥有a父 shell 有权访问的所有变量(特别是 )的自己的副本。当然,在子 shell 中所做的任何更改都不会反映在父 shell 中,因此:

$ a=100
$ (echo $a; a=200; echo $a)
100
200
$ echo $a
100
$

现在你的第二个例子:

$ cat b.sh
echo $a
$ a=100
$ ./b.sh

$ . ./b.sh
100
$ source ./b.sh
100
$ a=200 ./b.sh
200
$ echo $a
100
$ export a
$ ./b.sh
100
$

该变量a未导出,因此第一次b.sh运行时,它没有值,$a因此它回显了一个空行。后两个例子是“作弊”;shell 读取脚本b.sh,就好像它是当前 shell 的一部分(否fork()),所以变量仍然可以访问b.sh,因此它每次都回显 100。(点或是.在当前 shell 中读取脚本的旧机制;第 7 版 UNIX 中的 Bourne shell 使用它。该source命令是从 C shell 中借用的,作为等效机制。)

该命令在命令期间a=200 ./b.sh导出a,因此会b.sh看到并回显修改后的值200,但主 shella没有更改。然后当a导出时,它可以b.sh自动使用,因此它会看到并回显最后 100 个。

于 2013-05-20T15:42:50.177 回答