什么将使 `declare -A ASSOCIATIVEARRAY=( $())`工作?

什么将使 `declare -A ASSOCIATIVEARRAY=( $())`工作?

bash评估以下表达式,没有任何异议:

declare -A SPANISH=( [rojo]=red [verde]=green [azul]=blue )

...但它一点也不喜欢这个:

declare -A SPANISH=( $( echo "[rojo]=red [verde]=green [azul]=blue" ) )
bash: SPANISH: $( echo "[rojo]=red [verde]=green [azul]=blue" ): must use subscript when assigning associative array

我尝试了多种变体,但结果始终是must use subscript when assigning associative array上述错误的一个或多个实例。

当然,这个例子很愚蠢。其唯一目的是为了说明问题初始化一个巴什使用命令替换的关联数组

这可以做到吗?

具体来说,继续上面那个愚蠢的例子,<COMMAND>这样的命令是什么

declare -A SPANISH=( $( <COMMAND> ) )

...产生与产生的结果相同的最终结果

declare -A SPANISH=( [rojo]=red [verde]=green [azul]=blue )

多于?

顺便说一句,zsh处理这种情况没有任何问题:

$ declare -A SPANISH=( $( echo "rojo red verde green azul blue" ) )
$ echo "${SPANISH[azul]}"
blue

答案1

declare -A "SPANISH=($(echo '[rojo]=red [verde]=green [azul]=blue'))"

或者:

declare -A "SPANISH=$(echo '([rojo]=red [verde]=green [azul]=blue)')"

或者:

declare -A "$(echo 'SPANISH=([rojo]=red [verde]=green [azul]=blue)')"

就这一点而言,

为我使用 bash 5.1,尽管您也可以使用,eval因为这本质上就是这里发生的情况,bash 最终将命令的输出解释为代码。

例如,与

cmd() { echo '[x$(reboot)]=y'; }
declare -A "a=($(cmd))"

运行方式reboot与以下内容相同:

eval "
  declare -A a=($(cmd))
"

显式使用eval可以更清楚地表明存在命令注入漏洞的路径,并且更有可能是面向未来的,以防将来修复混乱的设计。

为了更安全的方法,您可以让您的cmd输出键和值以 NUL 分隔(因为 bash 变量无论如何都不能包含 NUL)并在循环中填充关联数组,但需要额外注意 bash 中的关联数组可以' t 有带空键的元素。

fill_assoc() {
  local -n _assoc="$1"
  local _key _value
  while
    IFS= read -rd '' _key &&
    IFS= read -rd '' _value
  do
     _assoc[$_key]=$_value
  done
}
typeset -A assoc
fill_assoc assoc < <(printf '%s\0' rojo red verde green azul blue)

相关内容