linux - shell 级别的变量范围

标签 linux bash shell

最近一直在看The Advanced Bash Script我发现一些关于父 shell 和子 shell 之间的变量范围 的事情让我非常困惑。在这里:

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

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

  1. (命令列表)

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

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

如何?

最佳答案

如果您在原始脚本中运行子 shell:

(command1; command2; ...)

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

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


直接解决您的示例:

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

在这里,子 shell 拥有父 shell 可以访问的所有变量(具体来说,a)的副本。当然,在子 shell 中所做的任何更改都不会反射(reflect)在父 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 但主 shell 的 a 没有变化。然后,当 a 被导出时,它自动可供 b.sh 使用,因此它会看到并回显最后的 100。

关于linux - shell 级别的变量范围,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/16653069/

相关文章:

linux - bash 脚本中的 [...] 代表什么?

bash - 如何使用 grep 从最后一行提取百分比?

linux - 这个简单的 C Shell 脚本有什么错误?

linux - 如何在后台运行脚本(linux openwrt)?

linux - 在停用另一个服务之前激活并运行 oneshot 服务

linux - 像 CGI 一样在 linux apache 中运行 EXE 文件

Linux 启动过程 -- iniramfs & root (\)

linux - QProcess 传递(shell)参数

linux - 编写 bash 脚本来更改文本并写入日志

linux - 我们可以在执行脚本后更改SHELL环境变量和解释器吗