1shell变量的作用域

  • Shell 局部变量
  • Shell 全局变量
    • shell全局变量的易错点:
    • linux shell中./a.sh , sh a.sh , source a.sh, . ./a.sh的区别
  • Shell 环境变量
    • shell配置文件

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

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

Shell 局部变量


原理

代码

输出结果

结论

Shell 支持自定义函数,但是 Shell 函数和其他编程语言函数的一个不同点就是:

在 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 进程,打开多个 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

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

b.sh

  1. #!/bin/bash
  2. echo $b
这三条命令都是在一个进程中执行的,从输出结果可以发现,在 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;

cat "/home/roaddb/test/55.txt" | while read line

do

let PARAM_NUMBER=${PARAM_NUMBER}+1;

done

echo "${PARAM_NUMBER}"

结果PARAM_NUMBER的值还是0,原因是在进行 cat的过程中, 相当于打开了一个新的shell,变量不在作用范围。

#!/bin/bash

PARAM_NUMBER=0;

while read line

do

let PARAM_NUMBER=${PARAM_NUMBER}+1;

done<"/home/roaddb/test/55.txt"

echo "${PARAM_NUMBER}"

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

echo $PPID 输出父进程号-------->589

 
执行方式 结果  
a.sh
报错bash: a.sh: command not found

 

./a.sh


bash: ./a.sh: Permission denied

需要权限,设置权限为777后执行

PID of this script: 92669

PPID of this script: 590

启了一个子shell来执行a.sh,所以可以看到PPID of this script: 590

sh ./a.sh 
PID of this script: 92878

PPID of this script: 590

sh a.sh 
PID of this script: 92928

PPID of this script: 590

source ./a.sh 
PID of this script: 590

PPID of this script: 589

在当前shell中执行脚本
source a.sh 
PID of this script: 590

PPID of this script: 589


. ./a.sh

两个点之间有空格


PID of this script: 590

PPID of this script: 589

../a.sh
报错bash: ../a.sh: No such file or directory

 

最后要说明的两点是:

1. 用sh和source去执行时, 不要求a.sh有可执行权限, 但单独./a.sh这样去搞时,需要可执行权限

2. 大家在开发项目时,经常需要设置环境变量, 当然是用source啊, 确保在当前shell生效

Shell 环境变量

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

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

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

使用env可以查看所有环境变量!!!

创建 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配置文件》。

原文地址:https://www.cnblogs.com/mianbaoshu/p/12069351.html

时间: 2024-08-02 19:41:27

1shell变量的作用域的相关文章

第四章—变量,作用域和内存问题(二)

第四章-变量,作用域和内存问题(二) JS没有块级作用域 js没有块级作用域,这个概念容易导致误解,这里就区分下几个情况,大家好好参考下: 我们知道,在其他类C的语言中,由花挂号封闭的代码块都有自己的作用域.但是在JS中,却没有块级作用域: 这里if(true){}代表条件永真,永远执行这条.if(false){}的话就是永远不执行这条. 这个代码执行之后,在if语句定义的变量,在if语句外可以访问的到.在if语句中的变量声明会将变量添加到当前的执行环境中(这里是全局环境). 还有如下的两个例子

Js中变量的作用域

一.理解函数作用域需要理解以下几点:    1.函数变量的作用域有全局变量和局部变量两种,全局变量写在函数的最前面,局部变量写在函数体内,局部变量省略了var 也就默认成为了全局变量!    2.函数体内部可以读取到函数外的变量,而函数外不能读取到函数内的变量! 在理解了函数变量的作用域之后,也需要理解函数的作用域链了:    1.每一个函数都有一个与之相关的作用域链,当js在查找变量X时,它会从链的第一个对象开始查找,如果这个对象有一个名为X的属性值,则会直接使用这个 属性值,如果没有就继续下

C的日记-变量的作用域、生存期和内存位置

“天地玄黄,宇宙洪荒”,先有天地,之后方有古今.变量同是,先有变量的作用域(存在的地点),然后出现了变量的生存期(存在的时间). [变量存储的方式]首先变量实际上是存放到两个区域的: 静态存储区:是指在程序运行区间由系统分配固定的存储空间的方式. 动态存储区:程序运行期间根据需要动态的分配存储空间. [变量分类] 局部变量:在[函数]内部声明的变量. [作用域]:从定义变量的位置到本函数结束. <1>自动变量(auto变量),即动态局部变量,不专门声明为static的变量.          

javaScript定义函数的三种方式&amp;amp;变量的作用域

一.函数定义 方式1.普通方式定义函数 function 函数名(參数n){ 函数体 } function add(a,b){ return a+b; } 方式2.直接量定义函数 var 函数名=function(參数n){ 函数体 } var add=function(a,b){ return a+b; } 方式三.构造方式定义函数 var 函数名=new Function(參数n,函数体); var add = new Function('a,b','return a+b;'); 二.变量的

Java中的变量与变量的作用域

关于Java中的变量及变量的作用域 关于Java中的变量及变量的作用域 0. 变量的概念 在程序运行期间,系统可以为程序分配一块内存单元,用来存储各种类型的数据.系统分配的内存单元要使用一个标记符来标识,这种内存单元中的数据是可以更改的.所有叫变量.定义变量的标记符就是变量名,内存单元中所装载的数据就是变量值.用一个变量定义一块内存以后,程序就可以用变量名代表这块内存中的数据.根据所存储数据类型的不同,有各种不同类型的变量. 1. Java的变量类型 2. 注意变量的有效取值范围 系统为不同的变

&lt;02&gt;关键字+标识符+常量表示+变量+作用域

标识符命名的规范 规范的内容:1)起一个有意义的名称  2)一般情况下遵守驼峰命名法 核心的思想: 1.如果一个标示符有多个单词组成 1)第一单词的首字母小写,其他单词的首字母都大写 2)或者所有的单词的首字母都大写 ------------------------------------------------ 常量的概述及分类 计算机中的常量:表示固定不变的数据,用常量来表示 常量的分类:整形常量.实型常量.字符常量.字符串常量 不同类型的常量表示方法 1)10进制整形常量(计算默认的使用1

变量和作用域的小结

有代码如下: var a = 5; function A(){ alert(a); var a = 10; alert(this.a); } new A(); 结果: undefined  undefined 第一个是变量提升,相当于 var a = 5; function A(){ var a ; alert(a);    //undefined a = 10;   //L3 alert(this.a); } new A(); 第二个,首先声明a是一个全局变量,函数A中又声明了一个局部变量,所

oc中的构造方法和description方法,变量的作用域,

1.构造方法的声明和实现 //声明 - (id) initWithAge:(int) age andNo: (int) no; //实现 - (id) initWithAge:(int) age andNo: (int) no { self=[super init];//调用父类的init方法初始化 //判断对象是否为空 也可以直接写if(self) 或 if(self=[super init]) if(self!=nil) { _age=age; _no=no; } return self;

黑马程序员 02-成员变量的作用域

———Java培训.Android培训.iOS培训..Net培训.期待与您交流! ——— 1.作用域基本概念 局部变量.全局变量都有自己的作用域,成员变量也不例外. 作用域的概念:在什么范围内可以访问,这个范围就是作用域. 2.成员变量的作用域类型 @public         在任何地方都可以直接访问 @protected    可以在当前类与子类的实现@implementation中直接访问,外界想访问只能用set  get方法访问 @private        只能在当前类的实现@im