Shell 变量的作用域(Scope),就是 Shell 变量的有效范围(可以使用的范围)。

在不同的作用域中,同名的变量不会相互干涉,就好像 A 班有个叫小明的同学,B 班也有个叫小明的同学,虽然他们都叫小明(对应于变量名),但是由于所在的班级(对应于作用域)不同,所以不会造成混乱。但是如果同一个班级中有两个叫小明的同学,就必须用类似于“大小明”、“小小明”这样的命名来区分他们。

Shell 变量的作用域可以分为三种:

  • 有的变量只能在函数内部使用,这叫做局部变量(local variable);
  • 有的变量可以在当前 Shell 进程中使用,这叫做全局变量(global variable);
  • 而有的变量还可以在子进程中使用,这叫做环境变量(environment variable)。

Shell 局部变量

Shell 也支持自定义函数,但是 Shell 函数和 C++、Java、C# 等其他编程语言函数的一个不同点就是:在 Shell 函数中定义的变量默认也是全局变量,它和在函数外部定义变量拥有一样的效果。请看下面的代码:

  1. #!/bin/bash
  2. #定义函数
  3. function func(){
  4. a=99
  5. }
  6. #调用函数
  7. func
  8. #输出函数内部的变量
  9. echo $a

输出结果:
99

a 是在函数内部定义的,但是在函数外部也可以得到它的值,证明它的作用域是全局的,而不是仅限于函数内部。

要想变量的作用域仅限于函数内部,可以在定义时加上local命令,此时该变量就成了局部变量。请看下面的代码:

  1. #!/bin/bash
  2. #定义函数
  3. function func(){
  4. local a=99
  5. }
  6. #调用函数
  7. func
  8. #输出函数内部的变量
  9. echo $a

输出结果为空,表明变量 a 在函数外部无效,是一个局部变量。

Shell 变量的这个特性和 JavaScript 中的变量是类似的。在 JavaScript 函数内部定义的变量,默认也是全局变量,只有加上var关键字,它才会变成局部变量。

本节只是演示了函数的定义和调用,并没有对语法细节作过多说明,后续我们将在《Shell函数》一节中进行深入讲解。

Shell 全局变量

所谓全局变量,就是指变量在当前的整个 Shell 进程中都有效。每个 Shell 进程都有自己的作用域,彼此之间互不影响。在 Shell 中定义的变量,默认就是全局变量。

想要实际演示全局变量在不同 Shell 进程中的互不相关性,可在图形界面下同时打开两个 Shell,或使用两个终端远程连接到服务器(SSH)。

首先打开一个 Shell 窗口,定义一个变量 a 并赋值为 99,然后打印,这时在同一个 Shell 窗口中是可正确打印变量 a 的值的。然后再打开一个新的 Shell 窗口,同样打印变量 a 的值,但结果却为空,如图 1 所示。


图1:打开两个 Shell 窗口

这说明全局变量 a 仅仅在定义它的第一个 Shell 进程中有效,对新的 Shell 进程没有影响。这很好理解,就像小王家和小徐家都有一部电视机(变量名相同),但是同一时刻小王家和小徐家的电视中播放的节目可以是不同的(变量值不同)。

需要强调的是,全局变量的作用范围是当前的 Shell 进程,而不是当前的 Shell 脚本文件,它们是不同的概念。打开一个 Shell 窗口就创建了一个 Shell 进程,打开多个 Shell 窗口就创建了多个 Shell 进程,每个 Shell 进程都是独立的,拥有不同的进程 ID。在一个 Shell 进程中可以使用 source 命令执行多个 Shell 脚本文件,此时全局变量在这些脚本文件中都有效。

例如,现在有两个 Shell 脚本文件,分别是 a.sh 和 b.sh。a.sh 的代码如下:

  1. #!/bin/bash
  2. echo $a
  3. b=200

b.sh 的代码如下:

  1. #!/bin/bash
  2. echo $b

打开一个 Shell 窗口,输入以下命令:

[c.biancheng.net]$ a=99
[c.biancheng.net]$ . ./a.sh
99
[c.biancheng.net]$ . ./b.sh
200

这三条命令都是在一个进程中执行的,从输出结果可以发现,在 Shell 窗口中以命令行的形式定义的变量 a,在 a.sh 中有效;在 a.sh 中定义的变量 b,在 b.sh 中也有效,变量 b 的作用范围已经超越了 a.sh。

注意,必须在当前进程中运行 Shell 脚本,不能在新进程中运行 Shell 脚本,不了解的读者请转到《执行Shell脚本》。

Shell 环境变量

全局变量只在当前 Shell 进程中有效,对其它 Shell 进程和子进程都无效。如果使用export命令将全局变量导出,那么它就在所有的子进程中也有效了,这称为“环境变量”。

环境变量被创建时所处的 Shell 进程称为父进程,如果在父进程中再创建一个新的进程来执行 Shell 命令,那么这个新的进程被称作 Shell 子进程。当 Shell 子进程产生时,它会继承父进程的环境变量为自己所用,所以说环境变量可从父进程传给子进程。不难理解,环境变量还可以传递给孙进程。

注意,两个没有父子关系的 Shell 进程是不能传递环境变量的,并且环境变量只能向下传递而不能向上传递,即“传子不传父”。

创建 Shell 子进程最简单的方式是运行 bash 命令,如图 2 所示。


图2:进入 Shell 子进程

通过exit命令可以一层一层地退出 Shell。

下面演示一下环境变量的使用:

[c.biancheng.net]$ a=22       #定义一个全局变量
[c.biancheng.net]$ echo $a    #在当前Shell中输出a,成功
22
[c.biancheng.net]$ bash       #进入Shell子进程
[c.biancheng.net]$ echo $a    #在子进程中输出a,失败[c.biancheng.net]$ exit       #退出Shell子进程,返回上一级Shell
exit
[c.biancheng.net]$ export a   #将a导出为环境变量
[c.biancheng.net]$ bash       #重新进入Shell子进程
[c.biancheng.net]$ echo $a    #在子进程中再次输出a,成功
22
[c.biancheng.net]$ exit       #退出Shell子进程
exit
[c.biancheng.net]$ exit       #退出父进程,结束整个Shell会话

可以发现,默认情况下,a 在 Shell 子进程中是无效的;使用 export 将 a 导出为环境变量后,在子进程中就可以使用了。

export a这种形式是在定义变量 a 以后再将它导出为环境变量,如果想在定义的同时导出为环境变量,可以写作export a=22

我们一直强调的是环境变量在 Shell 子进程中有效,并没有说它在所有的 Shell 进程中都有效;如果你通过终端创建了一个新的 Shell 窗口,那它就不是当前 Shell 的子进程,环境变量对这个新的 Shell 进程仍然是无效的。请看下图:

第一个窗口中的环境变量 a 在第二个窗口中就无效。

环境变量也是临时的

通过 export 导出的环境变量只对当前 Shell 进程以及所有的子进程有效,如果最顶层的父进程被关闭了,那么环境变量也就随之消失了,其它的进程也就无法使用了,所以说环境变量也是临时的。

有读者可能会问,如果我想让一个变量在所有 Shell 进程中都有效,不管它们之间是否存在父子关系,该怎么办呢?

只有将变量写入 Shell 配置文件中才能达到这个目的!Shell 进程每次启动时都会执行配置文件中的代码做一些初始化工作,如果将变量放在配置文件中,那么每次启动进程都会定义这个变量。不知道如何修改配置文件的读者请猛击《Shell配置文件的加载》《编写自己的Shell配置文件》。

Shell 变量的作用域相关推荐

  1. linux shell变量作用域,Shell变量的作用域:Shell全局变量、环境变量和局部变量

    Shell变量的作用域(Scope),就是Shell变量的有效范围(可以使用的范围). 在不同的作用域中,同名的变量不会相互干涉,就好像A班有个叫小明的同学,B班也有个叫小明的同学,虽然他们都叫小明( ...

  2. Linux中shell变量作用域笔记

    变量的作用域又可以叫做"命名空间",表示变量的上下文,同名的变量可以在多个命名空间定义,彼此互相独立. 在linux系统中,不同的进程ID的Shell默认为一个不同的命名空间. 比 ...

  3. shell基础(2):编程基础之变量:全局/局部/环境变量(作用域、定义、操作)、位置参数、数组

    对shell变量有一个系统性的了解 变量的种类:局部.全局.环境变量 变量的定义和操作:赋值.取值.取消变量 特殊变量:位置参数. $? 数组的定义和使用 变量的作用域 文章目录 1. 变量的种类 1 ...

  4. [转]Shell中脚本变量和函数变量的作用域

     转自:  http://blog.csdn.net/ltx19860420/article/details/5570902   在shell中定义函数可以使代码模块化,便于复用代码.不过脚本本身的变 ...

  5. Shell变量作用域

    总结 定义在函数外的变量为全局变量,作用域为定义位置开始到shell结束. 定义在函数内的变量,默认为全部变量,作用域为定义位置开始到shell结束,即函数内对变量的修改,会在函数外被访问到.变量前加 ...

  6. 马哥学习笔记——shell变量类型

    shell变量基础 shell 变量是一种很"弱"的变量,默认情况下,一个变量保存一个串,shell不关心这个串是什么含义.所以若要进行数学运算,必须使用一些命令例如let. de ...

  7. Linux中shell变量基础概念笔记

    1.变量的概念 其实shell中的变量是指向系统中一块存储数据的内存空间.变量的形式有局部变量和环境变量两种.并且shell变量属于弱类型的变量,可以不指定变量的类型就可以使用. 2.局部变量 局部变 ...

  8. JSON数据、字符串拼接、宽字符处理、数组、Notice警告、isset和empty、变量、作用域、常量、include和require

    JSON数据: 字面量是代码中表述数据的手段,JSON是一门类似于js字面量表述数据的手段,JSON是现在市面上用的最广的数据表述手段. 1.JSON对象中属性名称必须用双引号引起来 2.JSON中字 ...

  9. Linux 的 Shell 变量

    [简述] 变量即计算机中用于记录一个值的符号,而这些符号可用于不同的运算处理中. 通常变量与值是一对一的关系,可以通过表达式读取它的值并赋值给其它变量,也可以直接指定数值赋值给任意变量. 为便于运算和 ...

最新文章

  1. STM32使用GPIO_WriteBit()函数使LED灯闪烁
  2. IIS启动配置的一些命令
  3. django 模板里面for循环常用的方法
  4. java链式编程_Java 链式编程 和 lombok 实现链式编程
  5. Java黑皮书课后题第4章:*4.5(几何:正多边形的面积)正多边形是一个具有n条边的多边形,它每条边的长度都相等,而且所有角的度数也相等。编写程序,提示用户数输入边个数和边长,然后显示它的面积
  6. SAP Cloud for Customer根据模型某字段进行OData的搜索操作
  7. kafka学习_Kafka学习笔记下
  8. 电源管理 解析_智能电源控制箱
  9. 服务器电流源泉ups电源的三大形式
  10. C++ 后台程序实时性能监控
  11. JavaScript设计模式(一)-- 简单工厂模式
  12. Java进阶知识点:协变与逆变
  13. 数组 / 伪数组 判断及方法调用 (权威指南笔记)
  14. 小程序开发,不现实用户的头像!
  15. 制作ext4 img的两种方式
  16. macOS 汇编指南
  17. 5份简洁大方的个人简历模板,让你轻松应对面试
  18. 科大讯飞语音合成使用小记
  19. TCP 的四次挥手,可以变成三次挥手吗?
  20. raspberry 防火墙_用Raspberry Pi对您的家庭网络进行防火墙

热门文章

  1. Gartner:大数据投资增长,但计划投资的组织机构却在减少
  2. 控制iOS的导航栏和状态栏的样式
  3. QT 中使用 c++ 的指针
  4. ES6之字符串扩展方法(常用)
  5. C++ 类里面,函数占用存储空间问题
  6. 实现将一个字符串转化成对应的整形数字
  7. 关于MOSS SDK的Web Content Management
  8. 通讯系统经验谈【一】TCP连接状态分析:SYNC_RECV,CLOSE_WAIT,TIME_WAIT
  9. Kinect学习(四):提取深度数据
  10. 基于机器学习的捡球机器人设计与实现(探索)第4篇——机械设计)