Bash变量作用域泄漏

Bash变量作用域泄漏,bash,shell,environment-variables,Bash,Shell,Environment Variables,通常,我会看到人们无法从他们的范围之外访问变量的问题。然而,我似乎遇到了相反的情况:我看到变量仍然有来自内部作用域的值,它们应该在之后放弃。例如(使svn别名类似于): 我把它放在一个脚本中并对其进行源代码转换,所以它的函数被制作成bash的别名(我想)。尝试使用“-t”和“-f”的各种组合来运行此脚本,您将看到变量“$i”、“$j”和“$k”在再次运行脚本时都保持其值,并且在脚本退出后,它们在外壳中保持不变。我使用的是Ubuntu15.04笔记本电脑,当我键入Ctrl-XCtrl-V时,我的s

通常,我会看到人们无法从他们的范围之外访问变量的问题。然而,我似乎遇到了相反的情况:我看到变量仍然有来自内部作用域的值,它们应该在之后放弃。例如(使svn别名类似于):

我把它放在一个脚本中并对其进行源代码转换,所以它的函数被制作成bash的别名(我想)。尝试使用“-t”和“-f”的各种组合来运行此脚本,您将看到变量“$i”、“$j”和“$k”在再次运行脚本时都保持其值,并且在脚本退出后,它们在外壳中保持不变。我使用的是Ubuntu15.04笔记本电脑,当我键入
Ctrl-X
Ctrl-V
时,我的shell输出GNU bash,版本4.3.30(1)-发行版(x86_64-pc-linux-GNU)


我所读到的关于bash的所有信息都告诉我,这种情况不应该发生(诚然,我在这方面是个初学者)。在脚本(或函数)退出后,变量不应保持设置状态,除非对它们使用
export
,我没有这样做。那么为什么会发生这种情况呢?

有两种不同的现象在起作用:

  • 导出变量时,变量将被复制到子进程的环境中。不传递未导出的变量。除非明确使用
    export
    将变量标记为导出,否则不会导出变量

     export LESS_OPTIONS=-R   # export so `less` sees this variable
     less
    
    不要将其与范围混淆,范围是不同的

  • 默认情况下,函数内部变量具有全局范围。必须使用
    local
    关键字来声明局部变量。否则,类似“$@”中i的
    循环将修改全局变量
    $i
    ,而不是创建局部变量

    svn() {
        local i j k
    
        case $@ in
            ...
        esac
    }
    

  • 导出确定子进程看到的内容。作用域决定函数是否修改全局变量。

    这是否在正在运行的脚本中?或者是一个你正在寻找资源然后在命令行上调用函数的文件?第二个。我认为这与范围界定无关。我在互联网上的bash脚本示例中没有看到这一点。因此,在上面的示例中,我会使用类似于
    locali=$I
    的东西?许多野外编写的脚本都写得很糟糕。他们泄漏变量,他们没有正确引用变量,他们解析
    ps
    ls
    的输出。。。各种各样的胡说八道。在为
    循环使用
    之前,有一个正确使用
    local i
    的示例,以及注释,“函数中的局部变量
    i
    与外部脚本中的变量
    i
    存储不同。这允许两个循环在不干扰彼此计数器的情况下运行。”bash的作用域似乎与JavaScript类似。两者都有两种类型的作用域:全局作用域(无标识符)和函数作用域(用
    var
    local
    声明)。我有这个吗?我主要使用JavaScript,所以这样的类比对我很有帮助。是的,你是对的。我从来没有联系过。我想说JavaScript获胜是因为您可以将
    var
    声明放在
    for
    循环中。在bash中,它必须是一个单独的命令。
    declare
    也可以用于作用域。不幸的是,不使用
    local
    declare
    是一个常见错误。
    svn() {
        local i j k
    
        case $@ in
            ...
        esac
    }