如何以编程方式取消设置全局bash变量/管理Bash全局范围?

时间:2012-06-11 18:25:44

标签: bash scope

上下文

我们有几个基础架构由大量Bash脚本管理,这些脚本通过source命令相互交互,包括(并经常链接包含)符合标准Bash的文件我们使用的模板。我知道这种情况可能永远不会被允许,但这就是我们所拥有的。

模板基本上如下所示:

set_params() {
    #for parameters in a file that need to be accessed by other methods 
    #in that file and have the same value from initialization of that 
    #file to its conclusion:
    global_param1=value 

    #left blank for variables that are going to be used by other methods 
    #in the file, but don't have a static value assigned immediately:
    global_param2= 
}

main_internals() {
    #user-created code goes here.
}

main() {
    set_params
    #generic setup stuff/traps go here
    main_internals arg arg arg
    #generic teardown stuff goes here
}

使用这种结构,我们通过source命令将文件包含在其他文件中,然后调用包含的文件main方法,这些方法可以很好地包装和模块化大多数操作。

问题:

当一个新模块被添加到代码库时会出现一些最棘手的问题,这个代码库使用的全局变量名在其他地方使用,无关,在同一个source d链/文件集中。即如果file1.sh有一个名为myfile的变量用于某些事情,那么source s file2.sh,然后用myfile做更多的东西,并且写文件2的人.sh不知道(在很多情况下,他们不能指望 - 链接在一起的 lot 文件),他们可能会放置一个名为{{1}的非局部变量在file2.sh中,在file1.sh

中更改变量中具有相同名称的值

问题:

假设会出现全局变量名称冲突,并且{{1}一切都无法完全解决问题,是否有某种方法可以在编程时取消设置在执行期间在全局范围内设置的所有变量下面的特定功能或调用?有没有办法取消设置它们,而不会使用myfile相关脚本的文件所保留的相同名称取消设置?

答案很可能是“不”,但是在环顾四周之后并没有找到除“跟踪变量名称并在完成使用后取消任何内容”之外的其他内容(这将不可避免地导致代价高昂的错误) ,我想我会问。

另一种说法:有没有办法制作/破解像Bash中第三个作用域一样的东西? “本地到功能”和“此文件中运行的所有内容和此文件中的任何文件local可见”之间的某些内容“?

1 个答案:

答案 0 :(得分:3)

以下是未经测试的。

你可以像这样保存很多变量:

unset __var __vars
saveIFS=$IFS
IFS=$'\n'
__vars=($(declare -p))
IFS=$saveIFS

或通过将上面的最后一行更改为:

,根据公共前缀保存它们
__vars=($(declare -p "${!foo@}"))

然后你可以取消你需要的那些:

unset foo bar baz

或根据公共前缀取消设置:

unset "${!foo@}"

恢复变量:

for __var in "${__vars[@]}"
do
    $i
done

小心

  • 嵌入换行符的变量会做错误的事情
  • 带有空格的值会做错误的事情
  • 如果匹配前缀参数扩展返回空结果,declare -p命令将返回所有变量。

另一种更具选择性的技术可能是您特别知道当前函数中使用了哪些变量,因此您可以有选择地保存和恢复它们:

# save
for var in foo bar baz
do
    names+=($var)
    values+=("${!var}")
done

# restore
for index in "${!names[@]}"
do
    declare "${names[index]}"="${values[index]}"
done

使用变量名称而不是“var”,“index”,“names”和“values”,这些名称不太可能与其他人发生冲突。在函数内使用export而不是declare,因为declare强制变量是本地的,但随后会导出变量,这些变量可能会或可能不会产生不良后果。

建议:更换混乱,使用更少的全局变量或使用其他语言。

否则,请尝试我上面列出的内容,看看是否可以使用您的代码使其中的任何内容。