简体   繁体   English

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

[英]bash: defining a file-local variable invisible to sourcing script

Say I have a bash script file config.sh .假设我有一个 bash 脚本文件config.sh It's meant to be source'd by other scripts and variables defined is used as customization of the upper-level scripts.它意味着由其他脚本提供源代码,并且定义的变量用作上层脚本的自定义。

The problem is, if config.sh has 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 echo prints abc , not def .最后一个echo打印abc ,而不是def

Solution 1解决方案 1

My current solution is to append a random string to the temporary variable name to make it almost impossible to conflict.我目前的解决方案是在临时变量名后附加一个随机字符串,使其几乎不可能发生冲突。 eg:例如:

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 local keyword解决方案 2 使用local关键字

After some searching, I've come to know local keyword.经过一番搜索,我知道了local关键字。 But when I simply declare TMP1 as local , bash complains that config.sh: line 1: local: can only be used in a function .但是当我简单地将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.谢谢。

A trick I learned from the keychain utility is using one program to build a source -able file containing just the variables that you want to export from your program. 我从keychain实用程序中学到的一个技巧是使用一个程序来构建一个source代码文件,其中只包含要从程序中导出的变量。 You could modify your script to echo the variables you want to set and then source the output from your program: 您可以修改脚本以echo的变量,然后从程序中获取输出

$ echo $FOO

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

I used echo FOO=bar to simulate the larger script; 我使用echo FOO=bar来模拟更大的脚本; 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. 这使您可以决定公开哪些变量以及以另一个shell进程为代价保留私有变量。

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. 如果您仍然担心函数的名称冲突,这对您没有帮助。

The "ssh-agent" method: “ssh-agent”方法:

config.sh 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

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. 创建唯一文件名的两种常用方法是使用mktemp函数,该函数可保证创建唯一的文件名,或将PID嵌入文件名中。 The PID will be located in the variable '$$'. PID将位于变量“$$”中。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM