具有子函数的变量范围

时间:2014-12-29 00:46:16

标签: bash scope local-variables

我今天读了这篇文章

  

“Local只能在函数中使用;它使变量名称具有   可见范围仅限于该职能及其子女。“   ABS指南作者认为这种行为是一个错误。

§ Local Variables

我想出了这个脚本

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

所以你可以看到,因为我没有local bar,它泄露到了全球 范围。问题:

  • 一个局部变量可用于子函数实际上是一个bug,或者是 那只是他的意见?
  • Bash是否有办法在本地标记所有内容,类似于set -a标记的方式 出口的一切?
  • 如果不这样做,Bash有办法检查这些泄露的全局 变量?

2 个答案:

答案 0 :(得分:3)

  

一个局部变量是否可用于子函数实际上是一个bug,还是仅仅是他的意见?

不,这不是一个错误。这只是他的意见。

  

Bash是否有办法将所有内容标记为本地,类似于set -a标记出口的所有内容?

没有

  

如果不这样做,Bash是否有办法检查这些泄露的全局变量?

是。试试"设置"或"声明",两者都没有任何参数。

答案 1 :(得分:1)

  

如果不这样做,Bash是否有办法检查这些泄露的全局变量?

没有。 Bash有一个名为“隐藏变量”的无证概念,这使得无法测试是否设置了本地而不会干扰变量。

此测试演示隐藏变量以及unset内置函数的范围敏感性。

function f {
    case $1 in 1)
        typeset x=1
        f 2
        ;;
    2)
        typeset x
        unset -v x # Does nothing (demonstrates hidden local)
        f 3
        ;;
    [345])
        printf "x is %sunset\n" ${x+"not "}
        unset -v x
        f $(($1 + 1))
    esac
}

f 1

# output:
# x is unset
# x is not unset
# x is unset

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.