Shell变量作用范围

目录

1、函数内的变量

2、shell脚本内的变量

3、进程内的变量

4、进程间的变量

5、终端间的变量

6、用户间的变量

总结


本文内容同微信公众号【凡登】,关注不迷路,学习上高速,欢迎关注共同学习。

什么是变量的作用范围? 变量在Shell脚本中的有效范围或可使用的范围, 什么是有效范围或可使用范围? 通过看一个示例看看

# 定义一个变量
[root@ ~]# name=joey
# 编辑脚本hi.sh 内容为:echo "$name, hello",定义以脚本方式查看变量
[root@ ~]# vim hi.sh
echo "$name, hello"
# 当前终端查看
[root@ ~]# echo "$name, hello"
joey, hello
# 当前bash进程查看,能查看到变量
[root@ ~]# source ./hi.sh
joey, hello
# bash子进程查看,不能查看到变量
[root@ ~]# bash hi.sh
, hello
# 新启终端查看,不能查看到变量
[root@ ~]# echo "$name, hello"
, hello
# 回到最初终端,导出变量后可以查看到,
[root@ ~]# export name ; bash hi.sh
joey, hello

从上面可以看到,当前进程和终端可以访问当前定义的变量,而子进程和新启终端访问不到变量,

当回到原终端通过export导出变量后,这时子进程可以访问到变量,然而新终仍然无法访问到变量,这是什么原因? 它就是本小节将要介绍的主题:变量的作用范围

这里从简单到复杂,依次递进的方式将变量作用范围分为以下6种场景:函数内的变量shell脚本内的变量进程内的变量进程间的变量终端间的变量用户间的变量

1、函数内的变量

函数内的变量也就是局部变量。看下示例

[root@ ~]# vi fun.sh 
#!/bin/bash

function my_fun() {  
   echo "--------函数开始--------------"
   local local_var1="我是函数局部变量"  # 定义局部变量 var  
   echo "执行函数:$local_var1 !"  # 输出局部变量的值  
   echo "--------函数结束--------------"
}
 

echo "执行函数前:$local_var1 !"
my_fun  # 执行函数
echo "执行函数后:$local_var1 !"


[root@ ~]# bash fun.sh 
执行函数前: !
--------函数开始--------------
执行函数:我是函数局部变量 !
--------函数结束--------------
执行函数后: !

小结:局部变量在函数中有效,超过函数范围就失效

那可以在shell脚本中定义局部变量? 不可以。局部变量只能在函数中定义,

如下图错误示例:

[root@ ~]# vim fun_local_err.sh 
local v=123
[root@ ~]# bash fun_local_err.sh 
fun_local_err.sh: line 1: local: can only be used in a function

[root@ ~]# local vv=123
bash: local: can only be used in a function

2、shell脚本内的变量

在shell脚本中定义的变量作用范围分为:局部变量和全局变量,局部变量在某个区域内有效,如函数块内。全局变量时整个shell脚本运行中有效,一旦脚本运行结束,全局变量就会失效。这里重点介绍全局变量

[root@ ~]# vi fun.sh 
#!/bin/bash
global_var1="我是脚本全局变量"

function my_fun() {  
   echo "--------函数开始--------------"
   global_var2="我是函数全局变量"
   echo "执行函数:$global_var2 !"
   echo "--------函数结束--------------"
}
 
echo "执行函数前:$global_var1 !"
echo "执行函数前:$global_var2 !"
my_fun  # 执行函数
echo "执行函数后:$global_var1 !"
echo "执行函数后:$global_var2 !"



[root@ ~]# bash fun.sh 
执行函数前:我是脚本全局变量 !
执行函数前: !
--------函数开始--------------
执行函数:我是函数全局变量 !
--------函数结束--------------
执行函数后:我是脚本全局变量 !
执行函数后:我是函数全局变量 !

全局变量作用域在shell脚本都有效,访问前必须先定义好变量。忽略是否在函数中定义,如例子所示,即使在函数中定义,当函数执行完后,全局变量仍有效。

总结:局部变量只能在函数中定义和使用,且作用域在函数内。全局变量作用范围在整个脚本中,需要注意定义变量位置需在访问之前,且不受函数作用域范围的影响

3、进程内的变量

进程内变量描述的是bash进程中的变量。

在介绍进程内变量之前,先回顾下脚本执行不同方式所带来的影响,

bash xxx.sh 新起子进程执行xxx.sh , 脚本中行为只在子进程有效,对父进程环境没影响,

source ./xxx.sh 在当前进程执行xxx.sh ,脚本行为对当前进程环境有影响。

. xxx.sh 是source ./xxx.sh简写形式

./xxx.sh 新起子进程执行xxx.sh,

4种不同执行方式和区别详情参见《shell简单认知》脚本的执行方式。回到本节主题进程变量的作用范围

# 新建脚本hi.sh,内容为echo "$name, hello"
[root@ ~]# echo 'echo "$name, hello"' > hi.sh
# 当前进程新建变量name=123
[root@ ~]# name=123
[root@ ~]# echo $name
123

# bash xxx.sh执行脚本,以子进程方式访问访问父进程name
[root@ ~]# bash hi.sh
, hello

# source ./xxx.sh执行脚本,在当前进程访问name
[root@ ~]# source hi.sh
123, hello
# . xxx.sh 是 source ./xxx.sh的简写形式
[root@ ~]# . hi.sh
123, hello

# ./xx.sh子进程方式执行脚本
[root@ ~]# chmod u+x hi.sh
[root@ ~]# ./hi.sh
, hello

以上执行结果表明,同一进程变量访问不受限制,但子进程无法访问到父进程变量, 进程中的变量作用仅在当前进程的范围内有效,即进程变量也有自己的作用范围。

问:如何跨进程访问,让子进程也可以访问父进程变量,实现进程间的变量共享?

第4节《进程间的变量》

4、进程间的变量

进程间变量描述的是父子进程间变量。被export关键字修饰的变量,可以在进程间传递,也可以被子进程继承,从而在进程间实现变量共享。在第3节《进程内变量》例子中 bash hi.sh 访问不到name, 那么用export修饰name,再看执行结果

# 导出当前变量
[root@ ~]# export name

# bash xxx.sh 方式访问父进程变量name
[root@ ~]# bash hi.sh
123, hello
# ./xxx.sh 方式访问父进程变量name
[root@ ~]# ./hi.sh 
123, hello

执行结果看出,当用export修饰name变量后,就可以访问父进程name变量。

export命令设置的变量是环境变量

环境变量是在操作系统中用于存储各种配置信息的一种机制,通过设置环境变量,可以影响系统的行为和程序的运行。使用export命令,可以将一个变量从当前shell传递到子shell或其他进程中。当一个变量被导出后,它将成为子shell的环境变量,可以被其他命令和程序访问和使用

5、终端间的变量

在上一节学习了通过export修饰的变量可以在进程间传递,从而实现进程共享变量,那么能否在多个终端共享变量?先通过一个示例看看,在上述第4节《进程间的变量》例子中,新启一个终端,访问变量

# 新启终端访问
[root@ ~]#bash hi.sh
, hello

发现新启终端无法访问到上述通过export导出的环境变量,那么如何实现终端间的变量共享?

[root@ ~]# vim ~/.bashrc
export name=456

# 使用source ~/.bashrc加载配置文件
[root@ ~]# source ~/.bashrc 
# 访问可以看到原值123已经变为456
[root@ ~]# bash hi.sh
456, hello

# 新启终端访问,可以访问到最新值456
[root@ ~]#bash hi.sh
456, hello

说明:

1、修改~/.bashrc,如果不使用source ~/.bashrc加载,那么访问的仍然是原来的值;

当前终端立即访问,则需要通过source ~/.bashrc重新加载配置

新终端会重新加载配置,无需再使用source ~/.bashrc加载配置文件

2、写入~/.bashrc中的变量可以跨终端进行访问

在bashrc中修改的值无法被立即访问,是因为修改的变量只在当前Shell进程中生效,而不会影响到父进程或其他子进程。当在bashrc中添加或修改环境变量时,这些变量只会对当前Shell及其子进程起作用,而不会影响其他已经运行的Shell或系统级的环境变量

如果你希望在脚本中访问在bashrc中定义的变量,可以在脚本中通过source命令加载~/.bashrc文件。这样,脚本就会继承bashrc中定义的所有变量和配置。

通过上述bashrc配置文件实现终端共享变量。

6、用户间的变量

在上一节学习了通过export修饰的变量可以在进程间传递,从而实现进程共享变量;通过~/.bashrc配置变量实现跨终端共享变量,那么能否在不同用户间共享变量?先通过一个示例看看

# 创建新用户
[root@ ~]# useradd joy
[root@ ~]# passwd joy

# 创建脚本访问name和NAME变量
[root@ ~]# vi hi.sh 
echo "$name, hello"
echo "$NAME, hello"
echo "$_name, hello"
# 将root脚本复制到用户joy家目录下
[root@ ~]# cp /root/hi.sh /home/joy/

# 定义name和NAME,_name变量
[root@ ~]# name=123
[root@ ~]# export NAME=456
[root@ ~]# vim ~/.bashrc
export _name=123456

# 加载bashrc配置文件
[root@ ~]# source ~/.bashrc 
# root用户下访问变量
[root@ ~]# source ./hi.sh 
123, hello
456, hello
123456, hello

# 切换joy用户, 使用-表示用户登录加载所有配置文件
[root@ ~]# su - joy 
# joy用户下执行脚本访问变量
[joy@ ~]$ source ./hi.sh 
, hello
, hello
, hello

上面演示,不管是shell全局变量或通过export修饰的环境变量,还是定义在~/.bashrc配置文件的变量,当切换到新用户后都访问不到。说明这些不具备跨用户共享,那么如何才能做到切换用户仍然可以访问变量?

让我们在/etc/bashrc配置文件中新增变量,再观察一下

# 新增变量
[root@ ~]# vim /etc/bashrc
export _NAME=123456789
# 加载配置文件
[root@ ~]# source /etc/bashrc

# 在hi.sh后追加对_NAME的访问
[root@ ~]# vim hi.sh
echo "$_NAME, hello"
# 移动到joy用户家目录下
[root@ ~]# cp /root/hi.sh /home/joy/

# root用户下访问
[root@ ~]# source ./hi.sh 
123, hello
456, hello
123456, hello
123456789, hello

# 切换joy用户并登录
[root@ ~]# su - joy
# joy用户下访问变量,哎,这回可以访问_NAME变量,
[joy@ ~]$ source ./hi.sh
, hello
, hello
, hello
123456789, hello

注:编辑/etc/bashrc需要root权限

从上面结果可以看出当切换用户后,定义在/etc/bashrc下的变量仍可以访问,至此我们自定义的变量,实现了跨进程,跨终端,跨用户进行访问了。

总结

通过示例演示从函数->脚本->进程内->跨进程->跨终端->跨用户不同场景中变量表现,引出变量的作用范围,使用local修饰变量使变量的作用范围控制在函数内,在脚本中定义变量可以在函数中共享,通过使用export修饰变量使其能在进程间传递,实现进程间共享变量,扩大变量作用范围,另外修改配置文件~/.bashrc/etc/bashrc能使变量在多个终端和用户间共享,进一步扩大变量的作用范围,在日常工作中我们根据不同场景来限定变量范围,防止误伤。

问:~/.bashrc /etc/bashrc配置文件是什么?为什么可以实现变量共享?还有没有类似配置文件?

这些就是变量的配置文件,将在《变量配置文件》中讲解。

再次感谢您的阅读,欢迎关注微信公众号【凡登】共同学习。

  • 20
    点赞
  • 16
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
Shell脚本中,循环结构(如for循环和while循环)被用来重复执行相同或类似的命令或操作。循环中使用的变量是在循环内部定义的,它们的作用域仅限于该循环。 在for循环中,变量通常被用来迭代一个定长的列表或范围。在循环的每次迭代中,变量会被赋予列表中的下一个值,然后执行循环体中的命令。循环结束后,变量的值不再存在。 例如,以下是一个简单的for循环示例: ``` for fruit in apple banana orange do echo "I like $fruit." done ``` 在这个例子中,变量`fruit`被用来迭代列表中的水果名称。循环体中的`echo`命令会打印出相应的句子。每次循环时,`fruit`变量的值会依次是"apple"、"banana"和"orange"。当循环结束后,`fruit`变量不再存在。 类似地,在while循环中,变量通常用于判断循环是否应该继续执行。在循环的每次迭代中,条件被检查,如果为真,则执行循环体中的命令。如果在循环体内部改变变量的值,对其后续迭代没有影响。 例如,以下是一个简单的while循环示例: ``` count=0 while [ $count -lt 5 ] do echo "Count: $count" count=$((count + 1)) done ``` 在这个例子中,变量`count`被用于判断循环是否应该继续执行。只要`count`小于5,循环就会一直执行。在循环体中,首先打印出当前的`count`值,然后将其增加1。注意,`count=`的操作用于将`count`变量设置为0。 总之,Shell循环中的变量作用域仅限于循环本身,循环结束后变量的值不再存在。这使得我们可以方便地在循环中使用变量来迭代列表、判断循环条件等操作。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值