Warning: file_get_contents(/data/phpspider/zhask/data//catemap/5/bash/15.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Bash 带子函数的变量作用域_Bash_Scope_Local Variables - Fatal编程技术网

Bash 带子函数的变量作用域

Bash 带子函数的变量作用域,bash,scope,local-variables,Bash,Scope,Local Variables,我今天读了这篇文章 “局部只能在函数中使用;它使变量名具有 可视范围仅限于该函数及其子函数。” ABS指南作者认为这种行为是一个bug 我想出了这个剧本 begin () { local foo alpha } alpha () { foo=333 bar=444 bravo } bravo () { printf 'foo %3s bar %s\n' "$foo" "$bar" } begin bravo 输出 foo 333 bar 444 foo bar 4

我今天读了这篇文章

“局部只能在函数中使用;它使变量名具有 可视范围仅限于该函数及其子函数。” ABS指南作者认为这种行为是一个bug

我想出了这个剧本

begin () {
  local foo
  alpha
}
alpha () {
  foo=333 bar=444
  bravo
}
bravo () {
  printf 'foo %3s bar %s\n' "$foo" "$bar"
}
begin
bravo
输出

foo 333 bar 444
foo     bar 444
正如你们所看到的,因为我没有本地条码,所以它泄露到了全球 范围问题:

  • 子函数可用的局部变量实际上是一个bug,还是 那只是他的意见
  • Bash是否有一种方法可以标记所有本地内容,类似于
    set-a
    标记的方式 所有的东西都要出口吗
  • 如果不能做到这一点,Bash是否有办法检查这些泄露的全球信息 变量
子函数可用的局部变量实际上是一个bug,还是这只是他的观点

不,这不是虫子。那只是他的意见

Bash是否有一种将所有内容标记为本地的方法,类似于set-a将所有内容标记为导出

没有

如果不能做到这一点,Bash是否有办法检查这些泄漏的全局变量

对。只需尝试“set”或“declare”,两者都不带任何参数

子函数可用的局部变量实际上是一个bug,还是这只是他的观点

不,这不是虫子。那只是他的意见

Bash是否有一种将所有内容标记为本地的方法,类似于set-a将所有内容标记为导出

没有

如果不能做到这一点,Bash是否有办法检查这些泄漏的全局变量

对。只需尝试“set”或“declare”,两者都不带任何参数

如果不能做到这一点,Bash是否有办法检查这些泄漏的全局变量

不,Bash有一个未记录的概念,称为“隐藏变量”,这使得在不干扰变量的情况下无法测试是否设置了局部变量

这个测试演示了一个隐藏变量以及内置变量的范围敏感特性

Bash可以使用
declare-g
强制设置全局,但是无法强制Bash取消对它的引用,或者测试它是否已设置,这使得该功能的实用性非常有限

这很有希望清楚地说明这个问题

f() {
    local x="in x"      # Assign a local
    declare -g x=global # Assign a global
    declare -p x        # prints "in x"
    unset -v x          # try unsetting the local
    declare -p x        # error (x is invisible)
}
f
declare -p x # x is visible again, but there's no way to test for that before now.
如果不能做到这一点,Bash是否有办法检查这些泄漏的全局变量

不,Bash有一个未记录的概念,称为“隐藏变量”,这使得在不干扰变量的情况下无法测试是否设置了局部变量

这个测试演示了一个隐藏变量以及内置变量的范围敏感特性

Bash可以使用
declare-g
强制设置全局,但是无法强制Bash取消对它的引用,或者测试它是否已设置,这使得该功能的实用性非常有限

这很有希望清楚地说明这个问题

f() {
    local x="in x"      # Assign a local
    declare -g x=global # Assign a global
    declare -p x        # prints "in x"
    unset -v x          # try unsetting the local
    declare -p x        # error (x is invisible)
}
f
declare -p x # x is visible again, but there's no way to test for that before now.

明确地说,动态范围几乎总是被认为是语言设计的一个缺陷。在Bash(和大多数其他shell)的情况下,它是故意的,而不是偶然的“bug”。在Bash(和大多数其他shell)的例子中,这是故意的,不是偶然的“bug”。@StevenPenny我误解了吗?变量不能以意外地将局部设置为全局的方式“泄漏”(除了使用
declare-g
)。有意设置父作用域中声明的变量的最常见原因是模拟按引用传递,而无法测试本地化变量或保证引用特定实例这一事实是一个难题。如果目的是设置一个全局变量,那么同样的问题也适用
declare-g
保证设置了正确的实例,但设置后无法直接引用全局实例。没错,
unset
在脚本完成时剥离了所有层。当第一次点击
案例的最后一个分支时,
x
设置在第一个范围内,但测试(使用
${x+word}
)显示相反的结果。在从子作用域中实际取消设置x之前,无法区分x是否被设置。这正是您在示例问题中试图避免(或检测)的问题。代码/注释是正确的。如果bash的版本早于4.2alpha,那么就没有
声明-g
。它只是用来示范的。在调用
f
之前定义全局函数也会产生同样的效果,所以我用bash4.3再次尝试了这一点。函数之外只有
x
的全局值可用,那么问题出在哪里?@StevenPenny这就是第一条注释中描述的
declare-g
的陷阱(通常是动态范围的一个大问题)。
declare-g
的唯一功能是允许无条件分配到全局作用域,即使在当前作用域的任何父级中设置了具有相同名称的本地作用域。它不会使该变量在当前范围内可用,直到您从第一个本地化该变量的函数返回,或者从最后一个本地化该变量的任何子范围调用
unset
,直到所有具有冲突名称的局部变量都被取消设置为止。@StevenPenny我误解了吗?变量不能以意外地将局部设置为全局的方式“泄漏”(除了使用
declare-g
)。有意设置父作用域中声明的变量的最常见原因是模拟按引用传递,而无法测试本地化变量或保证引用特定实例这一事实是一个难题。如果目的是设置一个全局变量,那么同样的问题也适用
declare-g
保证设置了正确的实例,但设置后无法直接引用全局实例。没错,
unset
在脚本完成时剥离了所有层。当洛杉矶