Shell脚本 全局变量、局部变量
在不同的作用域中,同名的变量不会相互干涉,就好像 A 班有个叫小明的同学,B 班也有个叫小明的同学,虽然他们都叫小明(对应于变量名),但是由于所在的班级(对应于作用域)不同,所以不会造成混乱。但是如果同一个班级中有两个叫小明的同学,就必须用类似于“大小明”、“小小明”这样的命名来区分他们。
Shell 变量的作用域可以分为三种:
- 有的变量只能在函数内部使用,这叫做局部变量(local variable);
- 有的变量可以在当前 Shell 进程中使用,这叫做全局变量(global variable);
- 而有的变量还可以在子进程中使用,这叫做环境变量(environment variable)。
Shell 局部变量
Shell 也支持自定义函数,但是 Shell 函数和 C++、Java、C# 等其他编程语言函数的一个不同点就是:在 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函数》一节中进行深入讲解。
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 的代码如下:
- #!/bin/bash
- echo $a
- b=200
b.sh 的代码如下:
- #!/bin/bash
- 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脚本中局部变量local
shell脚本中局部变量 在shell中定义函数可以使代码模块化,便于复用代码.不过脚本本身的变量和函数的变量的作用域问题可能令你费解,在这里梳理一下这个问题. (1)Shell脚本中定义的变量是gl ...
- shell脚本一
在一些复杂的Linux维护工作中,大量重复的输入和交互操作不但费时费力,容易出错.这时候就需要用到脚本. 编写脚本的好处: 批量的处理,自动化的完成维护,减轻管理员的负担. linux的shell脚 ...
- Linux&shell之高级Shell脚本编程-创建函数
写在前面:案例.常用.归类.解释说明.(By Jim) 使用函数 #!/bin/bash # testing the script function myfun { echo "This i ...
- Linux Shell脚本编程的注意事项
Linux下(Shell脚本 http://www.jbxue.com/jb/shell/)编程的一些注意事项,如编程风格.命名风格等. 一.常用技巧 ssh user@server bash < ...
- Shell脚本编程总结及速查手册
Shell是一种编程语言, 它像其它编程语言如: C, Java, Python等一样也有变量/函数/运算符/if语句/循环控制/… 但在开始之前, 我想先理清Shell语言与Shell之间的关系. ...
- Shell脚本笔记
如何查询文件里的某个字符串? grep “字符串” 文件 例:grep "abc" tmp.txt 如何将查询出来的内容赋给变量? str=$(grep "abc ...
- 《Linux命令行与shell脚本编程大全》 第十六章 学习笔记
第十六章:创建函数 基本的脚本函数 创建函数 1.用function关键字,后面跟函数名 function name { commands } 2.函数名后面跟空圆括号,标明正在定义一个函数 name ...
- Shell 脚本常用命令
Shell脚本是Linux开发工作中常用的工具,但是我一直没有找到一个适合自己的简明扼要的HandBook.在工作过程中整理了一下,贴在这里已备查看. 1 Shell中的特殊符号 ...
- [转载]关于shell脚本的基本语法
关于shell脚本的基本语法 整理于:2014-03-31,何俭飞,mymladdr@sina.com 一.执行 1.shell脚本如果要被执行,一般地必须要有执行权限"x"(除了 ...
随机推荐
- 数据结构:堆(Heap)
堆就是用数组实现的二叉树,所有它没有使用父指针或者子指针.堆根据"堆属性"来排序,"堆属性"决定了树中节点的位置. 堆的常用方法: 构建优先队列 支持堆排序 快 ...
- Red Hat 操作系统 rpm 卸载软件提示"error: %preun( ) scriptlet failed, exit status 1"
在linux里安装程序有两种方法,一种是源程序安装,按照安装包里的readme或者install文件指示,一步步地进行,通常是configure, make, install三部曲.另一种就是rpm包 ...
- std::wcout输出1遍不输出
std::wcout输出1遍不输出 程序明明在执行地方执行 wcout无法输出到控制台 cout就可以 添加中文支持即可
- python 文件复制压缩
import os import time #这里是需要文件所在的位置 source=['"C:\\My Documents"',"C:\\Code"] #转换 ...
- Yii2使用PHPExcel读取excel
个人使用过程中保存一些使用PHPExcel的经验,以便后来翻阅:与PHP的Yii框架结合,可以轻松使用.而且根本不用网上所说的修改Yii的自动加载文件等方法.具体使用方法:下载phpoffice ht ...
- throws/throw Exception 异常应用
throws通常用于方法的声明,当方法中发生异常的时候,却不想在方法中对异常进行处理的时候,就可以在声明方法时, 使用throws声明抛出的异常,然后再调用该方法的其他方法中对异常进行处理(如使用tr ...
- python补充4
一 如何判断一个对象是不是函数类型 #方法一def func(arg): if callable(arg): print("是函数"+arg()) else: print(arg) ...
- [HCTF 2018]WarmUp
靶场首页 打开靶场后,查看源码即可看到<!--source.php--> 打开source.php页面 代码如下 <?php highlight_file(__FILE__) ...
- 【版本】Spring Cloud 版本
Spring Cloud 版本 Spring Cloud没有数字版本号,而是对应一个开发代号 Cloud代号 Boot版本(train) Boot版本(tested) lifecycle Angle ...
- hive的调优
调优 1 Fetch抓取(Hive可以避免进行MapReduce) Hive中对某些情况的查询可以不必使用MapReduce计算.例如:SELECT * FROM employees;在这种情况下,H ...