1shell变量的作用域
- Shell 局部变量
- Shell 全局变量
- shell全局变量的易错点
- linux shell中./a.sh , sh a.sh , source a.sh, . ./a.sh的区别
- Shell 环境变量
- shell配置文件
Shell 变量的作用域(Scope),就是 Shell 变量的有效范围(可以使用的范围)。Shell 变量的作用域可以分为三种:
1.有的变量只能在函数内部使用,这叫做局部变量(local variable)
2.有的变量可以在当前 Shell 进程中使用,这叫做全局变量(global variable)
3.有的变量可以在子进程中使用,这叫做环境变量(environment variable)
Shell 局部变量
|
原理
|
代码
|
|
结论
|
|---|---|---|---|
|
在shell函数中定义的变量为全局变量,与在函数外部定义变量的效果一样 |
#!/bin/bash
function func(){
|
func #调用函数 |
a 是在函数内部定义的,但是在函数外部也可以得到它的值, 证明它的作用域是全局的,而不是仅限于函数内部。 |
|
要想变量的作用域仅限于函数内部, 可以在定义时加上 |
#!/bin/bash
function func(){
|
func #调用函数 |
输出结果为空,表明变量 a 在函数外部无效,是一个局部变量。 Shell 变量的这个特性和 JavaScript 中的变量是类似的。 在 JavaScript 函数内部定义的变量,默认也是全局变量, 只有加上 |
Shell 全局变量
在 Shell 中定义的变量,默认就是全局变量,该变量在当前的整个 Shell 进程中都有效。
需要强调的是,全局变量的作用范围是当前的 Shell 进程,而不仅仅是当前的 Shell 脚本文件,它们是不同的概念。打开一个 Shell 窗口就创建了一个 Shell 进程,打开多个 Shell 窗口就创建了多个 Shell 进程,每个 Shell 进程都是独立的,拥有不同的进程 ID。在一个 Shell 进程中可以使用 source 命令执行多个 Shell 脚本文件,此时全局变量在这些脚本文件中都有效。
| 关注点 | 操作 | 对比1 | 对比2 | 其他 |
|---|---|---|---|---|
| 全局变量的作用范围是当前shell进程 | 打开两个shell窗口,验证变量作用域 |
打开一个 Shell 窗口,定义一个变量 b 并赋值为 88,然后打印,这时在同一个 Shell 窗口中是可正确打印变量 b 的值的。 |
再打开一个新的 Shell 窗口,同样打印变量 b 的值,但结果却为空。 |
|
| 全局变量的作用范围是不仅仅在当前的 Shell 脚本文件 | 在当前shell窗口定义变量a,可以被脚本1使用,在脚本1中定义的变量b,可以在脚本2中使用 |
a.sh
|
b.sh
|
这三条命令都是在一个进程中执行的,从输出结果可以发现,在 Shell 窗口中以命令行的形式定义的变量 a,在 a.sh 中有效; 在 a.sh 中定义的变量 b,在 b.sh 中也有效,变量 b 的作用范围已经超越了 a.sh。 |
|
在Shell 窗口,输入以下命令 a=99 . ./a.sh -->99 |
在同样的shell中执行. ./b.sh -->200 |
shell全局变量的易错点:
|
脚本
|
分析
|
|---|---|
PARAM_NUMBER=0; |
结果PARAM_NUMBER的值还是0,原因是在进行 cat的过程中, 相当于打开了一个新的shell,变量不在作用范围。 |
#!/bin/bash |
PARAM_NUMBER的值是正确的 |
linux shell中./a.sh , sh a.sh , source a.sh, . ./a.sh的区别
| 脚本 | 知识点 | |
|---|---|---|
| #! /bin/bash echo "PID of this script: $$" echo "PPID of this script: $PPID" |
echo $$ 输出当前进程号-------->590 |
|
| 执行方式 | 结果 | |
| a.sh |
报错bash: a.sh: command not found |
|
|
./a.sh |
bash: ./a.sh: Permission denied 需要权限,设置权限为777后执行 PID of this script: 92669 |
启了一个子shell来执行a.sh, 所以可以看到PPID of this script: 590 |
| sh ./a.sh |
PID of this script: 92878 |
|
| sh a.sh |
PID of this script: 92928 |
|
| source ./a.sh |
PID of this script: 590 |
在当前shell中执行脚本 |
| source a.sh |
PID of this script: 590 |
|
|
. ./a.sh 两个点之间有空格 |
PID of this script: 590 |
|
| ../a.sh |
报错bash: ../a.sh: No such file or directory |
最后要说明的两点是:
- 用sh和source去执行时, 不要求a.sh有可执行权限, 但单独./a.sh这样去搞时,需要可执行权限
- 大家在开发项目时,经常需要设置环境变量, 当然是用source啊, 确保在当前shell生效
Shell 环境变量
全局变量只在当前 Shell 进程中有效,对其它 Shell 进程和子进程都无效。如果使用export命令将全局变量导出,那么它就在所有的子进程中也有效了,这称为“环境变量”。
环境变量被创建时所处的 Shell 进程称为父进程,如果在父进程中再创建一个新的进程来执行 Shell 命令,那么这个新的进程被称作 Shell 子进程。当 Shell 子进程产生时,它会继承父进程的环境变量为自己所用,所以说环境变量可从父进程传给子进程或者孙进程。
注意,两个没有父子关系的 Shell 进程是不能传递环境变量的,并且环境变量只能向下传递而不能向上传递,即“传子不传父”。
使用env可以查看所有环境变量!!!
创建 Shell 子进程最简单的方式是运行 bash 命令,如图所示。
通过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会话
环境变量也是临时的,通过 export 导出的环境变量只对当前 Shell 进程以及所有的子进程有效,如果最顶层的父进程被关闭了,那么环境变量也就随之消失了,其它的进程也就无法使用了,所以说环境变量也是临时的。
shell配置文件
那如何让一个变量在所有 Shell 进程中都有效,不管它们之间是否存在父子关系呢?只有将变量写入 Shell 配置文件中才能达到这个目的!Shell 进程每次启动时都会执行配置文件中的代码做一些初始化工作,如果将变量放在配置文件中,那么每次启动进程都会定义这个变量。
1)shell 配置文件的加载
无论是否是交互式,是否是登录式,Bash Shell 在启动时总要配置其运行环境,例如初始化环境变量、设置命令提示符、指定系统命令路径等。这个过程是通过加载一系列配置文件完成的,这些配置文件其实就是 Shell 脚本文件。
与 Bash Shell 有关的配置文件主要有 /etc/profile、~/.bash_profile、~/.bash_login、~/.profile、~/.bashrc、/etc/bashrc、/etc/profile.d/*.sh,不同的启动方式会加载不同的配置文件。
~表示用户主目录。*是通配符,/etc/profile.d/*.sh 表示 /etc/profile.d/ 目录下所有的脚本文件(以.sh结尾的文件)。
登录式的 Shell
如果是登录式的 Shell,首先会读取和执行 /etc/profiles,这是所有用户的全局配置文件,接着会到用户主目录中寻找 ~/.bash_profile、~/.bash_login 或者 ~/.profile,它们都是用户个人的配置文件。
不同的 Linux 发行版附带的个人配置文件也不同,有的可能只有其中一个,有的可能三者都有。如果三个文件同时存在时,它们的优先级顺序是 ~/.bash_profile > ~/.bash_login > ~/.profile。
如果 ~/.bash_profile 存在,那么一切以该文件为准,并且到此结束,不再加载其它的配置文件。
如果 ~/.bash_profile 不存在,那么尝试加载 ~/.bash_login。~/.bash_login 存在的话就到此结束,不存在的话就加载 ~/.profile。
~/.bash_profile 中会加载 ~/.bashrc:
if [ -f ~/.bashrc ]; then
. ~/.bashrc
fi
非登录的 Shell
如果以非登录的方式启动 Shell,那么就不会读取以上所说的配置文件,而是直接读取 ~/.bashrc。
~/.bashrc 文件还会嵌套加载 /etc/bashrc,请看下面的代码:
if [ -f /etc/bashrc ]; then
. /etc/bashrc
fi
1shell变量的作用域的更多相关文章
- js学习之变量、作用域和内存问题
js学习之变量.作用域和内存问题 标签(空格分隔): javascript 变量 1.基本类型和引用类型: 基本类型值:Undefined, Null, Boolean, Number, String ...
- 深入理解 JavaScript 变量的作用域和作用域链
一个变量的作用域(scope)是程序源代码中定义这个变量的区域.简单的说,作用域就是变量与函数的可访问范围.全局变量拥有全局作用域,在JavaScript代码中的任何地方都有定义.局部变量是在函数体内 ...
- js变量及其作用域(附例子及讲解)
Javascript和Java.C这些语言不同,它是一种无类型.弱检测的语言.它对变量的定义并不需要声明变量类型,我们只要通过赋值的形式,可以将各种类型的数据赋值给同一个变量 工具/原料 Ch ...
- javascript变量的作用域
javascript变量的作用域 基本类型和引用类型 基本类型值指的是简单的数据段,而引用类型值指的是那个可能由多个值组成的对象 讲一个值赋值给变量时,javascript解析器首先要确定是基本类型 ...
- Js中变量的作用域
一.理解函数作用域需要理解以下几点: 1.函数变量的作用域有全局变量和局部变量两种,全局变量写在函数的最前面,局部变量写在函数体内,局部变量省略了var 也就默认成为了全局变量! 2.函数 ...
- 《征服 C 指针》摘录2:C变量的 作用域 和 生命周期(存储期)
在开发一些小程序的时候,也许我们并不在意作用域的必要性.可是,当你书写几万行,甚至几十万行的代码的时候,没有作用域肯定是不能忍受的. C 语言有如下 3 种作用域. 1.全局变量 在函数之外声明的变量 ...
- JavaScript变量和作用域
认识JavaScript中的变量 JavaScript中的变量有两种类型,一种是基本类型.一种是引用类型. 基本数据类型:Defined,Null,Boolean,Number,String.注意St ...
- JavaScript笔记:变量及其作用域
一.变量的定义及声明 在javascript中变量仅仅是用来保存值的一个占位符而已,定义变量时要使用关键字var后跟一个变量名,如下所示: var message; //定义一个变量message,像 ...
- JavaScript变量的作用域和函数的作用域的区别
变量作用域和函数作用域都涉及到变量值的变化,本文旨在让大家明白他们之间的区别 变量的作用域: 变量的作用域无非就是两种:全局变量和局部变量. Javascript语言的特殊之处,就在于函数内部可以直接 ...
随机推荐
- 10.2-3 ifup&ifdown:激活与禁用网络接口
ifup:激活网络接口 ifup 和 ifdown 命令用于激活指定的网络接口.ifup命令其实是一个Shel脚本,有Shel基础的读者可以使用which命令来找到这个脚本并读一读.命令可读取 ...
- MIPS指令的CPU实现:ALU设计
设计CPU的第一步,设计一个简单的逻辑运算单元ALU.同时对Verilog语言也有一定要求. 一.实验内容 如图,ALU接受两个N位的输入,得到N位的输出,通过控制信号F决定运算功能. 将ALU的输出 ...
- [Django高级之forms组件]
[Django高级之forms组件] forms组件之校验字段 # 第一步:定义一个类,继承forms.Form # 第二步:在类中写字段,要校验的字段,字段属性就是校验规则 # 第三步:实例化得到一 ...
- django2中namespace和name的使用
django2中namespace和name的使用 一.在Django <= 1.11 我们通过关键词namespace参数定义名称空间 1.projects/urls.py from ...
- 4D毫米波雷达Radar
4D毫米波雷达Radar 围绕雷达.激光雷达.高精定位等新一代传感器技术将会进入量产周期. 自动驾驶公司的竞争,在传感器配置上坦白说并没有太多差异化.除了车载激光雷达属于近几年的产物,类似摄像头.毫米 ...
- 英特尔Intel® Arria® 10 FPGA加速器设计
英特尔Intel Arria 10 FPGA加速器设计 Introducing the Intel Vision Accelerator Design with Intel Arria 10 FPGA ...
- 构造无限级树的框架套路,附上python/golang/php/js实现
目录 前言 需求 数据 结果 框架 递归框架 迭代框架 递归框架实现 python golang php js 迭代框架实现 python golang php js 前言 框架思维非常重要,和语言无 ...
- jmeter的参数化实现
背景: 在实际的测试工作中,我们经常需要对多组不同的输入数据,进行同样的测试操作步骤,以验证我们的软件的功能.这种测试方式在业界称为数据驱动测试,而在实际测试工作中,测试工具中实现不同数据输入的过程称 ...
- 包及权限配置&java存储机理绘制
包及权限配置 包的声明和导入 //声明 package aa.bb.cc; public class A{;} class B{;} //即在java输出目录aa.bb.cc中放入编译后的A.clas ...
- Spring Cloud专题之二:OpenFeign
欢迎查看上一篇博客:SpringCloud专题之一:Eureka . OpenFeign是一种声明式的webservice客户端调用框架.你只需要声明接口和一些简单的注解,就能像使用普通的Bean一样 ...