Bash可变范围泄漏

时间:2015-06-03 02:45:07

标签: bash shell environment-variables

通常,我会看到有关人们无法从其范围之外访问变量的问题。然而,我似乎正在经历相反的情况:我看到变量仍然具有内部范围的值,他们应该在之后放弃。例如(使svn别名类似于git aliases):

function svn() {
    case $@ in
        alias*) shift 1;
            for i in "$@"; do
                if [[ "$i" == "-t" ]];
                then
                    j="$i,$j"
                elif [[ "$i" == "-f" ]];
                    k="$i,$j"
                fi
            done

            echo "i = $i"
            echo "j = $j"
            echo "k = $k"
        ;;
    esac
}

我把它放在一个脚本中来源,所以它的功能是bash的别名(我想)。尝试使用“-t”和“-f”的各种组合运行它,你会看到变量“$ i”,“$ j”和“$ k”都会在再次运行脚本时保留它们的值,在脚本退出后,它们在外壳中保持不变。我使用的是Ubuntu 15.04笔记本电脑,当我输入Ctrl-X Ctrl-V时,我的shell输出GNU bash,版本4.3.30(1)-release(x86_64-pc-linux-gnu)。

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

1 个答案:

答案 0 :(得分:6)

有两种不同的现象:

  1. 当变量导出时,会将它们复制到子进程的环境中。未传递未导出的变量。除非您明确使用export将其标记为导出,否则不会导出变量。

     export LESS_OPTIONS=-R   # export so `less` sees this variable
     less
    

    不要将此与范围混淆,这是不同的。

  2. 默认情况下,内部函数变量具有全局范围。您必须使用local关键字来声明局部变量。否则,像for i in "$@"这样的循环将修改全局变量$i,而不是创建局部变量。

    svn() {
        local i j k
    
        case $@ in
            ...
        esac
    }
    
  3. 导出确定子进程看到的内容。范围确定函数是否修改全局变量。