Bash中局部变量已unset后如何访问全局变量
如何在函数unset同名局部变量后访问全局变量?
首先,咱们先弄明白为什么你的代码会得到2 3 1而不是预期的2 13 1:
问题根源:不同Shell的变量查找规则差异
如果你用的是POSIX兼容Shell(比如dash),一旦在函数内用local声明了某个变量,这个变量名在整个函数范围内都会被标记为「局部」。哪怕你unset了这个局部变量,后续对该变量名的引用依然会优先在局部作用域查找——而此时局部作用域已经没有这个变量了,所以会得到空值,自然输出3而不是13。
而在Bash中,unset局部变量后,后续的变量引用会自动回退到全局变量(如果存在),所以原代码在Bash中运行会得到你预期的2 13 1。看来你大概率是在POSIX Shell环境下执行的代码。
解决方法:跨Shell兼容的几种实现方式
1. 提前保存全局变量的值(最稳妥推荐)
在声明局部变量之前,把全局变量的值存到一个临时变量里,后续直接使用这个临时变量来引用全局值:
vv=1 cc() { local global_vv="$vv" # 先把全局vv的值存到临时变量 local vv=2 echo "$vv" unset vv echo "${global_vv}3" # 使用保存的全局值拼接输出 } cc echo "$vv"
这个方法在Bash和所有POSIX Shell中都能正常工作,执行结果就是你预期的:
2 13 1
2. 用eval强制解析全局变量(POSIX Shell专属)
在POSIX Shell中,可以借助eval强制让变量在全局作用域下解析:
vv=1 cc() { local vv=2 echo "$vv" unset vv eval echo "\$vv"3 # 通过eval让$vv指向全局变量 } cc echo "$vv"
这里的\$vv会被eval解析为全局的$vv,从而输出13。
3. 导出全局变量后用printenv获取(POSIX Shell适用)
如果可以把全局变量导出到环境变量,就能用printenv直接读取它的值:
export vv=1 # 将全局变量导出到环境 cc() { local vv=2 echo "$vv" unset vv echo "$(printenv vv)3" # 从环境变量中获取全局值 } cc echo "$vv"
注意:这个方法需要全局变量被导出,如果你不想影响其他环境,可以在使用后用export -n vv取消导出。
内容的提问来源于stack exchange,提问作者Buoy
相关产品推荐
相关产品推荐

