Shell 全局变量、环境变量和局部变量
Shell 变量的作用域(Scope),就是 Shell 变量的有效范围(可以使用的范围)。
在不同的作用域中,同名的变量不会相互干涉,就好像 A 班有个叫小明的同学,B 班也有个叫小明的同学,虽然他们都叫小明(对应于变量名),但是由于所在的班级(对应于作用域)不同,所以不会造成混乱。但是如果同一个班级中有两个叫小明的同学,就必须用类似于“大小明”、“小小明”这样的命名来区分他们。
Shell 变量的作用域可以分为三种:
- 有的变量可以在当前 Shell 会话中使用,这叫做全局变量(global variable);
- 有的变量只能在函数内部使用,这叫做局部变量(local variable);
- 而有的变量还可以在其它 Shell 中使用,这叫做环境变量(environment variable)。
全局变量
所谓全局变量,就是指变量在当前的整个 Shell 会话中都有效。每个 Shell 会话都有自己的作用域,彼此之间互不影响。在 Shell 中定义的变量,默认就是全局变量。
想要实际演示全局变量在不同 Shell 会话中的互不相关性,可在图形界面下同时打开两个 Shell,或使用两个终端远程连接到服务器(SSH)。
首先打开一个 Shell 窗口,定义一个变量 a 并赋值为 1,然后打印,这时在同一个 Shell 窗口中是可正确打印变量 a 的值的。然后再打开一个新的 Shell 窗口,同样打印变量 a 的值,但结果却为空,如图 1 所示。
图1:打开两个 Shell 会话
这说明全局变量 a 仅仅在定义它的第一个 Shell 中有效,对其它 Shell 没有影响。这很好理解,就像小王家和小徐家都有一部电视机(变量名相同),但是同一时刻小王家和小徐家的电视中播放的节目可以是不同的(变量值不同)。
需要强调的是,全局变量的作用范围是当前的 Shell 会话,而不是当前的 Shell 脚本文件,它们是不同的概念。打开一个 Shell 窗口就创建了一个 Shell 会话,打开多个 Shell 窗口就创建了多个 Shell 会话,每个 Shell 会话都是独立的进程,拥有不同的进程 ID。在一个 Shell 会话中,可以执行多个 Shell 脚本文件,此时全局变量在这些脚本文件中都有效。
例如,现在有两个 Shell 脚本文件,分别是 a.sh 和 b.sh。a.sh 的代码如下:
- #!/bin/bash
- echo $a
- b=200
b.sh 的代码如下:
- #!/bin/bash
- echo $b
打开一个 Shell 窗口,输入以下命令:
- $ a=99
- $ . ./a.sh
- 99
- $ . b.sh
- 200
- $
从输出结果可以发现,在 Shell 会话中以命令行的形式定义的变量 a,在 a.sh 中有效;在 a.sh 中定义的变量 b,在 b.sh 中也有效。
局部变量
Shell 也支持自定义函数,但是 Shell 函数和 C/C++、Java 等其他编程语言函数的一个不同点就是:在 Shell 函数中定义的变量默认也是全局变量,它和在函数外部定义变量拥有一样的效果。请看下面的代码:
- #!/bin/bash
- #定义函数
- function func(){
- a=99
- }
- #调用函数
- func
- #输出函数内部的变量
- echo $a
输出结果:
99
a 是在函数内部定义的,但是在函数外部也可以得到它的值,证明它的作用域是全局的,而不是仅限于函数内部。
要想变量的作用域仅限于函数内部,那么可以在定义时加上local
命令,此时该变量就成了局部变量。请看下面的代码:
- #!/bin/bash
- #定义函数
- function func(){
- local a=99
- }
- #调用函数
- func
- #输出函数内部的变量
- echo $a
输出结果为空,表明变量 a 在函数外部无效,是一个局部变量。
Shell 变量的这个特性和 JavaScript 中的变量是类似的。在 JavaScript 函数内部定义的变量,默认也是全局变量,只有加上var
关键字,它才会变成局部变量。
环境变量
全局变量只在当前 Shell 会话中有效,如果使用export
命令将它导出,那么它就在所有的子 Shell 中也有效了,这称为“环境变量”。
环境变量被创建时所处的 Shell 被称为父 Shell,如果在父 Shell 中再创建一个 Shell,则该 Shell 被称作子 Shell。当子 Shell 产生时,它会继承父 Shell 的环境变量为自己所用,所以说环境变量可从父 Shell 传给子 Shell。不难理解,环境变量还可以传递给孙 Shell。
注意,环境变量只能向下传递而不能向上传递,即“传子不传父”。
在一个 Shell 中创建子 Shell 最简单的方式是运行 bash 命令,如图 2 所示。
图2:进入子 Shell
通过exit
命令可以一层一层地退出 Shell。
下面演示一下环境变量的使用:
- $ a=22 #定义一个全局变量
- $ echo $a #在当前Shell中输出a,成功
- 22
- $ bash #进入子Shell
- $ echo $a #在子Shell中输出a,失败
- $ exit #退出子Shell
- exit
- $ export a #将a导出为环境变量
- $ bash #重新进入子Shell
- $ echo $a #在子Shell中再次输出a,成功
- 22
- $ exit #退出子Shell
- exit
- $ exit #退出父Shell,结束整个Shell会话
可以发现,默认情况下,a 在子 Shell 中是无效的;使用 export 将 a 导出为环境变量后,在子 Shell 中就可以使用了。
export a
这种形式是在定义变量 a 以后再将它导出为环境变量,如果想在定义的同时导出为环境变量,可以写作export a=22
。
注意,本节我们一直强调的是环境变量在子 Shell 中有效,并没有说它在所有的 Shell 种有效;如果你通过终端创建一个新的 Shell,那么它就不是当前 Shell 的子 Shell,环境变量对这个 Shell 就是无效的。
此外,通过export
命令导出的环境变量是临时的,关闭 Shell 会话后它就销毁了。所以,这种环境变量也只是在局部范围内起作用,并不影响所有 Shell。
如果想让环境变量在所有 Shell 中都有效,并且能够永久保存,在关闭 Shell 后也不丢失,那么就需要把环境变量写入启动文件。至于如何写入文件,请大家自行百度,这里就不再赘述了。
Shell 全局变量、环境变量和局部变量的更多相关文章
- Shell基础-环境变量配置文件
Shell基础-环境变量配置文件 source 配置文件 或者 . 配置文件: 把环境变量写入配置文件后,需要用户重新登陆才能生效,而是用source命令,则能直接生效 主要的配置文件: /etc/p ...
- awk中使用shell的环境变量
awk中使用shell的环境变量一:"'$var'"这种写法大家无需改变用'括起awk程序的习惯,是老外常用的写法.如:var="test"awk 'BEGIN ...
- Shell编程——环境变量
在Shell程序启动时会自动定义一组变量,这组变量就是环境变量,系统中的所有命令都可以使用这些变量参数. 1.如果在父Shell定义环境变量,在子Shell中也能查看到. (1)父Shell与子She ...
- Shell变量的作用域:Shell全局变量、环境变量和局部变量
Shell 变量的作用域(Scope),就是 Shell 变量的有效范围(可以使用的范围). 在不同的作用域中,同名的变量不会相互干涉,就好像 A 班有个叫小明的同学,B 班也有个叫小明的同学,虽然他 ...
- Linux下的Shell编程(2)环境变量和局部变量
Shell Script是一种弱类型语言,使用变量的时候无需首先声明其类型. 局部变量在本地数据区分配内存进行存储,这个变量归当前的Shell所有,任何子进 程都不能访问本地变量.这些变量与环境变量不 ...
- Linux编程 11(shell全局环境变量与局变环境变量)
一.概述 在linux中,很多程序和脚本都通过环境变量来获取系统信息,存储临时数据,配置信息.环境变量是指用来存储有关shell会话和工作环境信息,允许你在内存中存储数据,以便程序或shell中运行的 ...
- Linux Shell基础 环境变量
环境变量 环境变量和用户自定义变量最主要的区别在于,环境变量是全局变量,而用户自定义变量是局部变量.用户自定义变量只在当前的 Shell 中生效,而环境变量会在当前 Shell 和这个 Shell 的 ...
- shell配置环境变量
我们在使用Xshell开发机时往往会遇到一些问题,比如使用某些命令他会报command not found,,出现这种情况的原因是我们必须要配置一下环境变量,这样就可以在任何path中访问了. 这就需 ...
- Linux编程 21 shell编程(环境变量,用户变量,命令替换)
一.概述 这篇介绍shell的变量使用,跟其实语言一样,都有声明变量,使用变量,在shell中变量允许你临时地将信息存储中shell脚本中,以便和脚本的其他命令一起使用. 1.1 环境变量 在前面章节 ...
随机推荐
- 数据库 【redis】 命令大全
以下纯属搬砖,我用Python抓取的redis命令列表页内容 如果想看命令的具体使用可查去官网查看,以下整理为个人查找方便而已 地理位置GEOADD 将指定的地理空间位置(纬度.经度.名称)添加到指定 ...
- Linux新手随手笔记1.8
配置网卡服务 将网卡的配置文件,保存成模板,叫做会话. nmcli命令查看网卡信息.nmcli是一款基于命令行的网络配置工具 只有一个网卡信息,下面我们再添加一个. 公司:静态IP地址 家庭:DHCP ...
- redis缓存类
<?php class Redis_model{ public $redis = null; public function __construct() { $hosts = $this-> ...
- Promise探讨
一.前言 大家都知道JavaScript一大特点就是单线程,为了不阻塞主线程,有些耗时操作(比如ajax)必须放在任务队列中异步执行.传统的异步编程解决方案之一回调,很容易产生臭名昭著的回调地狱问题. ...
- 使用ASP.NET Core开发GraphQL服务器 -- 预备知识(上)
为了介绍使用ASP.NET Core构建GraphQL服务器,本文需要介绍一下GraphQL,其实看官网的文档就行. 什么是GraphQL? GraphQL 既是一种用于 API 的查询语言也是一个满 ...
- pip安装python库时使用国内镜像资源加速下载过程
pip默认安装包是从网站https://pypi.org/simple下载,我们可以将其改成国内的镜像网站,加速下载过程,下面以安装numpy库为例: pip install -i https://p ...
- HTTP 内容编码,也就这 2 点需要知道 | 实用 HTTP
Hi,大家好,我是承香墨影! HTTP 协议在网络知识中占据了重要的地位,HTTP 协议最基础的就是请求和响应的报文,而报文又是由报文头(Header)和实体组成.大多数 Http 协议的使用方式,都 ...
- 【Android Studio安装部署系列】十八、Android studio更换APP应用图标
版权声明:本文为HaiyuKing原创文章,转载请注明出处! 概述 Android Studio新建项目后会有一个默认图标,那么如何更换图标呢? 替换图标 这个方案不建议直接在已有项目上更换图标,建议 ...
- JavaScript一看就懂(2)闭包
认识闭包之前需要先了解作用域,如果你对作用域还没有足够了解,请移步JavaScript一看就懂(1)作用域 什么是闭包? 我们可以先简单认为:一个函数a定义在另一个函数b里面,这个函数a就是闭包: f ...
- C# 10分钟完成百度人脸识别——入门篇
嗨咯,小编在此祝大家新年快乐财多多! 今天我们来盘一盘人脸注册.人脸识别等相关操作,这是一个简单入门教程. 话不多说,我们进入主题: 完成人脸识别所需的步骤: 注册百度账号api,创建自己的应用: 创 ...