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)