bash:定义一个对源脚本不可见的文件局部变量

时间:2012-02-09 03:25:38

标签: bash

假设我有一个bash脚本文件config.sh。它意味着由其他脚本提供源代码,定义的变量用作上层脚本的自定义。

问题是,如果config.sh有一个临时变量且其名称与上层脚本的变量冲突,则会破坏上层脚本。

config.sh:

TMP1=abc
CONFIG_INPUT_DIR="$TMP1"/in
CONFIG_OUTPUT_DIR="$TMP1"/out

高级脚本:

TMP1=def
source config.sh
echo $TMP1

最后echo次打印abc,而不是def

解决方案1 ​​

我目前的解决方案是将一个随机字符串附加到临时变量名称,以使其几乎不可能发生冲突。 e.g:

TMP1_vFc9Uiew=abc
CONFIG_INPUT_DIR="$TMP1_vFc9Uiew"/in
CONFIG_OUTPUT_DIR="$TMP1_vFc9Uiew"/out
unset TMP1_vFc9Uiew

这很痛苦并且使代码难以阅读,此外并不完美。

使用local关键字

的解决方案2

经过一番搜索后,我开始了解local个关键字。 但是当我简单地将TMP1声明为local时,bash会抱怨config.sh: line 1: local: can only be used in a function

所以我的另一个解决方案是将整个配置脚本作为函数包含在内:

function config_func_rZ0Yqkpm() {
  local TMP1=abc
  CONFIG_INPUT_DIR="$TMP1"/in
  CONFIG_OUTPUT_DIR="$TMP1"/out
}
config_func_rZ0Yqkpm
unset config_func_rZ0Yqkpm

在可维护性和可读性方面优于以前的解决方案,但是存在冲突和解决方案1的可能性。

问题

我想知道更强大,更智能的解决方案,没有任何冲突的可能性。

感谢。

4 个答案:

答案 0 :(得分:8)

您可以避免变量并使用config.sh中的函数来保存您的值:

get_dirname() { echo "abc"; }
CONFIG_INPUT_DIR="$(get_dirname)/in"
CONFIG_OUTPUT_DIR="$(get_dirname)/out"
unset -f get_dirname

如果您仍然担心功能的名称冲突,这对您没有任何帮助。

答案 1 :(得分:7)

我从keychain实用程序中学到的一个技巧是使用一个程序构建一个source - 只能包含要从程序中导出的变量的文件。您可以将脚本修改为echo要设置的变量,然后从程序中获取输出

$ echo $FOO

$ source <(echo FOO=bar)
$ echo $FOO
bar
$ 

我使用echo FOO=bar来模拟更大的脚本;你的程序可能更复杂。重要的是,您必须修改程序以输出您想要设置的变量和值,而不是仅设置它们。这使您可以决定公开哪些变量以及以另一个shell进程为代价保留私有变量。

答案 2 :(得分:7)

“ssh-agent”方法:

config.sh

#!/bin/bash
TMP=abc
printf "CONFIG_INPUT_DIR=%s/in" "$TMP"
printf "CONFIG_OUTPUT_DIR=%s/out" "$TMP"

主程序:

TMP1=def
eval $(config.sh)
echo $TMP1

答案 3 :(得分:0)

创建唯一文件名的两种常用方法是使用mktemp函数,该函数可保证创建唯一的文件名,或将PID嵌入文件名中。 PID将位于变量“$$”中。