shell基础之变量(2):变量有哪些种类、怎么定义/赋值/取值、不同种类变量的作用域

本文详细介绍了Shell脚本中的变量,包括全局变量、局部变量和环境变量的定义、操作及作用域。全局变量在整个Shell进程中有效,局部变量仅限于函数内部,而环境变量通过export命令可以在子进程中继承。此外,还讲解了变量的赋值、取值和取消操作,以及变量命名规则。

通过本文能对shell变量有一个系统性的了解,具体的包括:

  1. 变量的种类:局部、全局、环境变量
  2. 变量的定义和操作:赋值、取值、取消变量
  3. 变量的作用域

变量指向一片用于存储数据的内存空间。
shell变量是一种弱类型的变量,即在声明变量时不需要指定其类型

一. 变量的种类

1. 全局变量

所谓全局变量,就是指变量在当前的整个 Shell 进程中都有效每个 Shell 进程都有自己的作用域,彼此之间互不影响。在 Shell 中定义的变量,默认就是全局变量。

需要强调的是,全局变量的作用范围是当前的 Shell 进程,而不是当前的 Shell 脚本文件,它们是不同的概念。

打开一个 Shell 窗口就创建了一个 Shell 进程,打开多个 Shell 窗口就创建了多个 Shell 进程,每个 Shell 进程都是独立的,拥有不同的进程 ID。在一个 Shell 进程中可以使用 source 命令执行多个 Shell 脚本文件,此时全局变量在这些脚本文件中都有效。

打开一个 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。

 

2. 局部变量:local

默认情况下:

Shell 函数中定义的变量默认是全局变量,它和在函数外部定义变量拥有一样的效果。

如下shell 列子:

#!/bin/bash
#定义函数
function func(){
    a=99
}
#调用函数
func
#输出函数内部的变量
echo $a
执行shell
99

 

通过关键字 local 可以声明变量仅在函数中生效

#!/bin/bash
#定义函数
function func(){
    local a=99
}
#调用函数
func
#输出函数内部的变量
echo $a


输出结果为空,表明变量 a 在函数外部无效,是一个局部变量。

 

3. 环境变量

全局变量只在当前 Shell 进程中有效,对其它 Shell 进程和子进程都无效。

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

a. 环境变量的继承

父子shell与环境变量的继承:

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

 
环境变量与父子shell

[c.biancheng.net]$ a=22       #定义一个全局变量
[c.biancheng.net]$ echo $a    #在当前Shell中输出a,成功
22
##进入shell子进程 ing
[c.biancheng.net]$ bash       #进入Shell子进程
[c.biancheng.net]$ echo $a    #在子进程中输出a,失败

[c.biancheng.net]$ exit       #退出Shell子进程,返回上一级Shell
exit
#将a导出为环境变量 子进程可以查到
[c.biancheng.net]$ export a   
[c.biancheng.net]$ bash       #重新进入Shell子进程
[c.biancheng.net]$ echo $a    #在子进程中再次输出a,成功
22
# 通过exit命令可以一层一层地退出 Shell。
[c.biancheng.net]$ exit       #退出Shell子进程
exit
[c.biancheng.net]$ exit       #退出父进程,结束整个Shell会话

注意:如果通过终端创建了一个新的 Shell 窗口,那它就不是当前 Shell 的子进程,环境变量对这个新的 Shell 进程是无效的。

 

b. 预设的环境变量

可以使用echo命令查看变量的值
在这里插入图片描述

bash-3.2$ ECHO $PATH
/usr/local/bin:/usr/bin:/bin:/usr/sbin:/sbin:/Applications/VMware Fusion.app/Contents/Public
#(重设)添加路径到PATH

# 仅对当前shell有效
bash-3.2$ export PATH=/somepath/path:$PATH
bash-3.2$ echo $PATH
/somepath/path:/usr/local/bin:/usr/bin:/bin:/usr/sbin:/sbin:/Applications/VMware Fusion.app/Contents/Public

 
 

二. 变量命名

shell中的变量必须以字母或者下划线开始,变量是区分大小写的

 
 

三. 变量操作

1. 赋值:

  1. 变量名和变量值之间没有空格
  2. 当变量值有空格时必须使用引号括起

 

2. 取值:

  • 取值时变量名前添加$ ,但更严谨的是 ${} 。
  • 双引号与单引号:变量值引用其他变量值时必须使用双引号,因为单引号会阻止Shell解释特殊字符 $。
gaoliang@MacBook-Pro demo % name=joho
gaoliang@MacBook-Pro demo % name1="$name"
gaoliang@MacBook-Pro demo % echo $name1  
joho
gaoliang@MacBook-Pro demo % name1='$name'
gaoliang@MacBook-Pro demo % echo $name1  
$name

 

3. 取消变量:unset

取消变量是将变量从内存中释放,使用unset可以实现。

gaoliang@MacBook-Pro demo % unset Var 
gaoliang@MacBook-Pro demo % echo $Var

 
 

四. 变量的作用域

1. 全局变量的作用域

Shell变量的作用域:

  • 从定义该变量的地方开始到shell结束
  • 或是主动使用unset删除该变量的地方为止
[root@tbds-10-1-0-38 log]# cat nameSpace2.sh 
#!/bin/bash
echo before func Var1 is $0:$Var1
Var1=200
 
# 定义函数
function fun1(){
        Var1=121
}
 
echo before func Var1 is $0:$Var1
#执行函数
fun1
echo after func Var1 is $0:$Var1
 
 
[root@tbds-10-1-0-38 log]# bash nameSpace2.sh 
before func Var1 is run_quan.sh:
before func Var1 is run_quan.sh:200
after func Var1 is run_quan.sh:121

 
全局变量只在当前shell有效,如下例子:

[root@tbds-10-1-0-38 log]# cat nameSpace1.sh 
#!/bin/bash
Var1=100
echo var1 is $0:$Var1
#调用bash
bash nameSpace2.sh

[root@tbds-10-1-0-38 log]# cat nameSpace2.sh 
#!/bin/bash
# nameSpace1的Var1仅在自己的shell脚本中有效,
Var1=200
echo Var1 is $0:$Var1


[root@tbds-10-1-0-38 log]# bash nameSpace1.sh 
var1 is nameSpace1.sh:100
Var1 is nameSpace2.sh:200

 

2. 局部变量的作用域

添加local指定局部变量

[root@tbds-10-1-0-38 log]# cat nameSpace2.sh 
#!/bin/bash
Var1=200
 
function fun1(){
        local Var1=121
}
 
echo before func Var1 is $0:$Var1
fun1
echo after func Var1 is $0:$Var1
#因为局部变量只在函数中起作用,所以执行完函数之后,输出的值还是全局变量
[root@tbds-10-1-0-38 log]# bash nameSpace2.sh 
before func Var1 is nameSpace2.sh:200
after func Var1 is nameSpace2.sh:200

<think>我们正在讨论Shell脚本中的变量赋值语法:${TOOLDIR:=/home/el/tools} 这个语法是Shell参数扩展的一种形式,具体是使用“:=”操作符。它的含义是: - 如果变量 TOOLDIR 已经设置且非空,则使用它的当前值。 - 如果变量 TOOLDIR 未设置或为空,则将它设置为等号后面的值(即/home/el/tools),并使用这个新值。 这种语法常用于在脚本中为变量设置默认值,以避免变量定义时导致的错误。 使用场景: 1. 在脚本中,我们可能希望使用一个环境变量,但如果用户没有设置该环境变量,则使用一个默认值。 2. 这样写可以确保后续脚本运行中该变量一定有一个非空的值。 注意:与另一种类似语法 ${TOOLDIR-/home/el/tools} 的区别: - 使用减号(-)时,如果变量未设置,则整个表达式会扩展为默认值,但不会将默认值赋给变量。 - 而使用(:=)时,如果变量未设置或为空,不仅整个表达式会使用默认值,而且还会将默认值赋给变量(即修改变量的值)。 因此,${var:=default} 既提供了默认值,又确保了变量var之后不再为空。 示例: 假设我们有一个脚本,需要用到TOOLDIR变量,但用户可能没有设置: echo "工具目录是: ${TOOLDIR:=/home/el/tools}" 如果之前没有设置TOOLDIR,执行这行后,TOOLDIR的值就会被设置为/home/el/tools,并且后续脚本中都可以使用这个值。 另外,如果变量TOOLDIR之前已经设置(比如设置为/home/el/mytools),那么上面的语句就不会改变它的值,而是直接使用/home/el/mytools。 引用说明: 在站内引用[1]中提到了awk的使用,虽然与这个语法没有直接关系,但awk脚本中也可能用到类似的变量处理。不过,我们这里讨论的是Shell脚本的变量扩展。 另外,引用[3]是部署zabbix的脚本,其中可能包含类似的变量设置,但具体内容没有直接给出。 因此,根据我们的知识,我们可以这样解释: 回答: 在Shell脚本中,表达式 `${TOOLDIR:=/home/el/tools}` 是一种参数扩展,用于为变量 `TOOLDIR` 设置默认值。具体行为如下: - 如果 `TOOLDIR` 未被设置或为空(null),则将其赋值为 `/home/el/tools`,然后使用该值。 - 如果 `TOOLDIR` 已经被设置且非空,则直接使用其原有值。 这种语法通常用于确保脚本中使用的变量具有有效的值,避免因变量定义而导致的错误。 使用场景示例: 在脚本开头,我们可以这样设置: TOOLDIR=${TOOLDIR:=/home/el/tools} 或者直接在需要使用该变量的地方使用,例如: echo "工具目录设置为: ${TOOLDIR:=/home/el/tools}" 注意:这种赋值方式只在当前Shell环境中有效。如果希望该变量在脚本执行后仍然保留,需要使用export将其导出为环境变量。 与 `${TOOLDIR-/home/el/tools}` 的区别: 后者在变量未设置(不包括空)时,会返回默认值但不赋值变量。而 `:=` 在变量未设置或为空时都会进行赋值。 参考Shell脚本的相关文档[^1](因为站内引用[1]提到了Shell脚本,虽然具体内容是关于awk的,但整个文档是关于Shell的,所以我们可以参考这个文档的上下文)以及Shell编程的通用知识。 相关问题: 根据用户的问题,生成相关问题: §§相关问题§§ 1. Shell脚本中 `${var:=value}` 和 `${var-value}` 有什么区别? 2. 在Shell脚本中,如何将变量设置为只读以防止被修改? 3. 除了 `:=`,Shell参数扩展还有哪些常用的操作符? 4. 如何让一个Shell脚本中设置的变量在脚本执行结束后仍然有效? </think>### Shell 脚本中 `${TOOLDIR:=/home/el/tools}` 的解释 #### 1. **语法含义** - `${TOOLDIR:=/home/el/tools}` 是 Shell 的**参数扩展语法**,用于变量的**默认值赋值**。 - **行为逻辑**: - 若 `TOOLDIR` **未定义或为空**: 将变量设为 `/home/el/tools`,并返回该值。 - 若 `TOOLDIR` **已定义且非空**: 直接返回变量的当前值,**不修改**原值。 #### 2. **关键特性** - **同时完成赋值取值**: 一步操作实现变量的条件赋值和值提取。 - **空值视为未定义**: 变量值为空字符串(`TOOLDIR=""`)时,仍会触发赋值。 - **局部作用域**: 赋值仅在当前 Shell 或脚本中生效。 #### 3. **典型使用场景** - **脚本配置初始化** 为路径类变量提供默认值,避免手动检查: ```bash # 确保 TOOLDIR 有有效值 TOOLDIR="${TOOLDIR:=/home/el/tools}" echo "工具目录: $TOOLDIR" ``` - **依赖外部输入的健壮性处理** 当变量可能来自不稳定环境(如用户输入、配置文件)时: ```bash # 若用户未提供输入,则使用默认路径 process_data --dir="${INPUT_DIR:=/opt/default_data}" ``` - **避免未定义变量导致的错误** 在关键操作前强制变量有效: ```bash cd "${WORKSPACE:=/tmp/workspace}" # 防止 cd 失败 ``` #### 4. **与类似语法的区别** | 语法 | 行为 | |-----------------------|----------------------------------------------------------------------| | `${VAR:=default}` | **空或未定义赋值**并返回默认值 | | `${VAR-default}` | 仅当**未定义**时返回默认值,不赋值(空值仍返回空) | | `${VAR:-default}` | 空或未定义时返回默认值,**不赋值** | | `${VAR:?error_msg}` | 空或未定义时报错退出(用于强制校验) | #### 5. **示例验证** ```bash # 场景1:变量定义 unset TOOLDIR echo "结果: ${TOOLDIR:=/home/el/tools}" # 输出结果: /home/el/tools echo "当前值: $TOOLDIR" # 输出当前值: /home/el/tools # 场景2变量为空 TOOLDIR="" echo "结果: ${TOOLDIR:=/home/el/tools}" # 输出结果: /home/el/tools echo "当前值: $TOOLDIR" # 输出当前值: /home/el/tools # 场景3:变量有值 TOOLDIR="/custom/path" echo "结果: ${TOOLDIR:=/home/el/tools}" # 输出结果: /custom/path echo "当前值: $TOOLDIR" # 输出当前值: /custom/path ``` #### 6. **注意事项** - **不可用于只读变量**:若变量被声明为 `readonly`,尝试赋值会报错。 - **兼容性**:主流的 Bash、Zsh、Ksh 均支持此语法(POSIX 兼容)。 - **优先使用环境变量**:若需跨脚本共享,建议用 `export VAR=${VAR:=default}`。 此语法在脚本中广泛用于提升健壮性,尤其在自动化部署(如引用[3]的 Zabbix 脚本)或系统工具开发(如引用[1]的 awk 文本处理)中避免路径错误[^1][^3]。 ---
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
红包 添加红包
表情包 插入表情
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

roman_日积跬步-终至千里

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值