Arrays bash循环在不覆盖先前声明的变量的情况下分配变量值

Arrays bash循环在不覆盖先前声明的变量的情况下分配变量值,arrays,bash,variables,global-variables,associative-array,Arrays,Bash,Variables,Global Variables,Associative Array,我们目前的设置是在一个配置文件中声明几个变量,然后运行一些依赖于这些变量的进程。我试图提供的其他功能是一个default_variables脚本,它将为配置文件中的所有变量提供默认值,同时不会覆盖配置文件中声明的任何内容 这是我目前的代码: #!/bin/bash -x # allows var to be used as an associative array declare -A var # variable declarations must be of the form: # va

我们目前的设置是在一个配置文件中声明几个变量,然后运行一些依赖于这些变量的进程。我试图提供的其他功能是一个default_variables脚本,它将为配置文件中的所有变量提供默认值,同时不会覆盖配置文件中声明的任何内容

这是我目前的代码:

#!/bin/bash -x

# allows var to be used as an associative array
declare -A var

# variable declarations must be of the form:
# var[var_name]=var_value
# after processing loop, the above will be evaluated as:
# export var_name=var_value

# declare default variables
var[a]=a_val
var[b]=b_val
var[c]=c_val
var[d]=d_val

# iterate on associative array indices
for default_var in `echo "${!var[@]}"`
do

test_var=\$${default_var}

  # only export variables that have not been previously declared
  if [[ -z `eval $test_var` ]]
  then

    # export each index name as a variable
    export $default_var=${var[$default_var]}
  fi
done
我当前遇到的错误是eval语句试图执行变量的值,如果它是在脚本运行之前声明的。例如,如果上面的脚本运行两次,则错误为:

-sh: a_val: command not found
-sh: b_val: command not found
-sh: c_val: command not found
-sh: d_val: command not found
现在我肯定会想出一个更优雅的方法来解决这个问题,但这是我能想到的最好的方法。最后,我知道正常导出值并单独检查每个变量以查看它们是否已分配是一种更“正确”的方法,但我不想让脚本呈指数级膨胀,也不想让人们在每次向脚本添加新变量时都要复制逻辑,而且我不能在配置文件之前运行default_variables脚本,允许它覆盖默认值,因为某些默认值依赖于配置值


提前感谢您的帮助

不要使用
eval
,这会导致其参数作为命令执行。您所需要的只是由
$default\u var
命名的变量的值。间接变量引用有一个非常好的语法:

if [[ -z ${!default_var} ]]
虽然您确实想测试非空<代码>-z测试是否为空。应该如此

if [[ -n ${!default_var} ]]
此外,这一点过于复杂,而且可以说是不正确的:

for default_var in `echo "${!var[@]}"`
只要写下:

for default_var in "${!var[@]}"
现在,这只检查变量是否未设置或为空,即用户不能显式将变量设置为空:

$ a= ./banana
a=a_val
b=b_val
c=c_val
d=d_val
要支持此操作,您可以改为执行以下操作:

for default_var in "${!var[@]}"; do     #<=== no ugly `echo ...` needed
    if ! declare -p "$default_var" &>/dev/null; then
    # export each index name as a variable
        export "$default_var=${var[$default_var]}" #<=== use quotes!
    fi
done

我会这样做:

# iterate on associative array indices (no need to do `echo ...`)
for default_var in "${!var[@]}"
do
    # skip variables that have been previously declared (even if their value is null)
    if [[ -z ${!default_var+.} ]]
    then
        # export each index name as a variable (the safer way with quotes)
        export "$default_var=${var[$default_var]}"
    fi
done

没错,先生!除了-n选项之外,我想测试是否为空,因为如果它为空,那么我想分配一个值,否则跳过它,但是${!default_var}完成了任务,实际上不需要echo命令。我试图对我的第一个脚本草稿过于谨慎,因为我嵌套了变量:)啊,我现在看到,我的评论实际上误导了我的意图,就-n/-z而言。我将其改写为“仅导出以前未声明的变量”
[!-v$default\u var]
。fwiw@rici为真,但仅启动bash 4.2是的。只有十年前的三分之一。当然,仍然有人认为C99太新奇了。我希望你不要开玩笑地认为所有用户都能轻松升级他们的系统。一点也不。我自己仍然使用电传打字机与大型机进行通信,就像我开始从事这一领域以来所做的那样。虽然我的手指越来越累了,但没有咔嗒声就感觉不舒服。
for default_var in "${!var[@]}"; do     #<=== no ugly `echo ...` needed
    if ! declare -p "$default_var" &>/dev/null; then
    # export each index name as a variable
        export "$default_var=${var[$default_var]}" #<=== use quotes!
    fi
done
$ a= ./banana
a=
b=b_val
c=c_val
d=d_val
# iterate on associative array indices (no need to do `echo ...`)
for default_var in "${!var[@]}"
do
    # skip variables that have been previously declared (even if their value is null)
    if [[ -z ${!default_var+.} ]]
    then
        # export each index name as a variable (the safer way with quotes)
        export "$default_var=${var[$default_var]}"
    fi
done