1

语境:

我们有几个基础设施由大量 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是 file2.sh,然后用 做更多的事情myfile,而编写 file2.sh 的人不知道(在许多情况下他们不能可以预期 - 有很多文件链接在一起),他们可能会在 file2.sh 中放置一个名为的非局部变量myfile,更改 file1.sh 中具有相同名称的变量中的值

问题:

假设会出现全局变量名称冲突,并且local一切都不能完全解决问题,有没有办法以编程方式取消在执行特定函数或调用期间在全局范围内设置的所有变量?有没有一种方法可以取消设置它们,而无需取消设置相关脚本文件所包含的具有相同名称的其他变量source

答案很可能是“不”,但是在环顾四周并没有发现除了“跟踪变量名并在使用完毕后取消设置任何东西”(这将不可避免地导致代价高昂的错误)之外,我想我会问。

换一种说法:有没有办法制作/破解类似于 Bash 中的第三个作用域的东西?介于“函数的本地”和“此文件中运行的所有内容以及该文件的任何文件可见”之间的东西source

4

1 回答 1

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强制变量是本地的,但是变量将被导出,这可能会或可能不会产生不良后果。

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

否则,请尝试我上面概述的内容,看看您是否可以使用您拥有的代码使其中的任何一个工作。

于 2012-06-11T19:18:33.807 回答