【问题标题】:What is the difference between global scope and environment?全局范围和环境有什么区别?
【发布时间】:2020-06-22 12:14:46
【问题描述】:

全局作用域和环境一样吗?

declare builtin 有一个 -g 选项:

-g 选项强制在全局范围内创建或修改变量,即使在 shell 函数中执行声明时也是如此。在所有其他情况下都将被忽略。

【问题讨论】:

标签: bash


【解决方案1】:

TL;DR 全局作用域在启动时从环境初始化,但与环境不同。


环境是父进程提供的一组<name>=<value> 形式的字符串。在启动时,shell 会获取每个 <name> 部分是有效 shell 标识符的字符串,并在全局范围内使用该名称创建一个变量。

例如,环境字符串FOO=3 变成一个名为FOO 的shell 变量,其值为3

另一方面,像10=6 这样的环境字符串会被shell 忽略,因为10 不是有效的shell 标识符。但是,该字符串仍保留在环境中,以传递给可能需要这样一个字符串的任何子进程。 [更新:POSIX 规范不要求忽略此类字符串;符合要求的外壳可以保留或丢弃它们。]

还有局部变量,由函数定义中的localdeclare 等命令创建。例如:

$ foo () { declare x; x=3; echo "$x"; }
$ x=2
$ foo
3
$ echo "$x"
2

x=2 在全局范围内创建(或更改值)一个变量。在函数内部,declare x 创建了一个局部变量。对该变量的更改不会影响同名的全局变量。

declare-g 选项让您可以让函数内部的名称 x 引用全局范围,而不是创建局部变量。

$ foo () { declare -g x; x=3; echo "$x"; }
$ x=2
$ foo
3
$ echo "$x"
3

【讨论】:

  • shell 是否丢弃具有无效名称的环境变量(从环境中取消设置,而不仅仅是在转换为 shell 变量时忽略)取决于版本并且 POSIX 未指定。我们在知识库中有一个关于它的问题 - 至少其中一些在后 shellshock 时代早期开始被 bash 破坏。
  • "[...];应用程序应容忍此类名称的存在。"似乎非常清楚地表明不应仅仅因为 shell (或其他 POSIX 实用程序)无法使用它们而从环境中删除名称。
  • 继续阅读。 未指定在调用时传递给 shell 的环境变量是否包含在传递给 execl() 和(如果 execl() 如上所述失败)到新的 shell。 这是来自 shell 命令语言规范,而不是环境变量规范。
  • 呃。就 POSIX 规范而言,这似乎是不必要的狡猾。
猜你喜欢
  • 2021-07-25
  • 1970-01-01
  • 2014-12-22
  • 2013-08-19
  • 2012-12-11
  • 2015-09-22
  • 2019-01-29
  • 2013-12-01
  • 1970-01-01
相关资源
最近更新 更多