bash:定义一个对采购脚本不可见的文件局部变量
声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow
原文地址: http://stackoverflow.com/questions/9205000/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me):
StackOverFlow
bash: defining a file-local variable invisible to sourcing script
提问by niboshi
Say I have a bash script file config.sh. It's meant to be source'd by other scripts and variables defined is used as customization of the upper-level scripts.
假设我有一个 bash 脚本文件config.sh。它意味着由其他脚本提供源,定义的变量用作上级脚本的自定义。
The problem is, if config.shhas a temporary variable and its name conflicts with upper-level scripts' variable, it breaks the upper-level one.
问题是,如果config.sh有一个临时变量并且它的名称与上层脚本的变量冲突,它会破坏上层的变量。
config.sh:
配置文件:
TMP1=abc
CONFIG_INPUT_DIR="$TMP1"/in
CONFIG_OUTPUT_DIR="$TMP1"/out
upper-level script:
上层脚本:
TMP1=def
source config.sh
echo $TMP1
The last echoprints abc, not def.
最后echo打印abc,没有def。
Solution 1
方案一
My current solution is to append a random string to the temporary variable name to make it almost impossible to conflict. e.g:
我目前的解决方案是在临时变量名后附加一个随机字符串,使其几乎不可能发生冲突。例如:
TMP1_vFc9Uiew=abc
CONFIG_INPUT_DIR="$TMP1_vFc9Uiew"/in
CONFIG_OUTPUT_DIR="$TMP1_vFc9Uiew"/out
unset TMP1_vFc9Uiew
which is painful and makes the code hard to read, in addition not to be perfect.
这很痛苦,使代码难以阅读,而且不完美。
Solution 2 using localkeyword
使用local关键字的解决方案2
After some searching, I've come to know localkeyword.
But when I simply declare TMP1as local, bash complains that config.sh: line 1: local: can only be used in a function.
经过一番搜索,我知道了local关键字。但是,当我简单地声明TMP1的local,bash的抱怨config.sh: line 1: local: can only be used in a function。
So my another solution is to enclose whole config script as 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
which is better than previous solution in maintainability and readability, but there's some possibility to conflict as well as solution 1.
这在可维护性和可读性方面比以前的解决方案要好,但与解决方案 1 一样,存在一些冲突的可能性。
Question
题
I want to know more robust and smart solution without any possibility to conflict.
我想知道更强大和更智能的解决方案,而没有任何冲突的可能性。
Thanks.
谢谢。
采纳答案by sarnold
A trick I learned from the keychainutility is using one program to build a source-able file containing just the variables that you want to export from your program. You could modify your script to echothe variables you want to set and then source the outputfrom your program:
我从该keychain实用程序中学到的一个技巧是使用一个程序来构建一个source仅包含要从程序中导出的变量的-able 文件。您可以将脚本修改为echo要设置的变量,然后从程序中获取输出:
$ echo $FOO
$ source <(echo FOO=bar)
$ echo $FOO
bar
$
I used echo FOO=barto simulate the larger script; your program is probably more involved. The important part is that you must modify your program to output the variables and values you would like to set, rather than just setting them. This lets you decide which variables to expose and which ones to hold private at the cost of another shell process.
我曾经echo FOO=bar模拟过较大的脚本;您的计划可能涉及更多。重要的部分是您必须修改您的程序以输出您想要设置的变量和值,而不仅仅是设置它们。这使您可以决定要公开哪些变量以及以另一个 shell 进程为代价将哪些变量保持为私有。
回答by glenn Hymanman
You could avoid variables and use functions in config.sh to hold your values:
您可以避免使用变量并使用 config.sh 中的函数来保存您的值:
get_dirname() { echo "abc"; }
CONFIG_INPUT_DIR="$(get_dirname)/in"
CONFIG_OUTPUT_DIR="$(get_dirname)/out"
unset -f get_dirname
If you're still concerned about name collision for functions, this doesn't really help you.
如果您仍然担心函数的名称冲突,这对您没有帮助。
回答by glenn Hymanman
The "ssh-agent" method:
“ssh-agent”方法:
config.sh
配置文件
#!/bin/bash
TMP=abc
printf "CONFIG_INPUT_DIR=%s/in" "$TMP"
printf "CONFIG_OUTPUT_DIR=%s/out" "$TMP"
main program:
主程序:
TMP1=def
eval $(config.sh)
echo $TMP1
回答by Barton Chittenden
The two usual methods of creating a unique file name are to use the mktemp function, which is guaranteed to create a unique file name, or to embed the PID in the file name. The PID will be located in the variable '$$'.
创建唯一文件名的两种常用方法是使用 mktemp 函数,该函数保证创建唯一文件名,或者在文件名中嵌入 PID。PID 将位于变量“$$”中。

