Почему этот синтаксис не работает для объявления ассоциативного массива

Почему этот синтаксис не работает для объявления ассоциативного массива

Могу ли я использовать переменную внутри синтаксиса ()

#!/bin/bash
declare -A c
declare -A b
a="[a]=0 [b]=1 [c]=2 [d]=3"
b=($a) # or b=($(echo "$a"))
echo "***********${b[@]}*********"  #********************

c=([a]=0 [b]=1 [c]=2 [d]=3)
echo "---------${c[@]}----------"  #---------0 1 2 3----------

решение1

В настоящее время (насколько мне известно) невозможно брать строки и создавать с ними ассоциативные массивы в Bash. Поэтому вы должны "оценить" их перед использованием оператора eval.

При запуске вашего примера с использованием Bash версии 4.1.7 я получаю следующее:

$ ./arr.bash 
./arr.bash: line 5: b: [a]=0: must use subscript when assigning associative array
./arr.bash: line 5: b: [b]=1: must use subscript when assigning associative array
./arr.bash: line 5: b: [c]=2: must use subscript when assigning associative array
./arr.bash: line 5: b: [d]=3: must use subscript when assigning associative array

Изменение строки на эту работает:

eval "b=($a)" # or b=($(echo "$a"))

Повторив запуск, вы получите ожидаемые результаты:

$ ./arr.bash 
***********0 1 2 3*********
---------0 1 2 3----------

Объяснение

Я нашел этот SO Q&A под названием:Bash: Как присвоить ассоциативный массив другому имени переменной (например, переименовать переменную)?, который иллюстрирует метод, позволяющий это сделать, declareно он показывает, насколько нечитабельным на самом деле является этот метод, и, вероятно, его не следует использовать.

# declare associative array
declare -A assoc_array=(["key1"]="value1" ["key2"]="value2")
# convert associative array to string
assoc_array_string=$(declare -p assoc_array)
# create new associative array from string
eval "declare -A new_assoc_array="${assoc_array_string#*=}
# show array definition
declare -p new_assoc_array

Этот метод показывает, что $assoc_arrayпреобразуется в строку, а затем преобразуется обратно в ассоциативный массив, $new_assoc_array. Но даже этот метод не может избежать необходимости использовать eval. Это сложный для понимания фрагмент кода, и он показывает, почему его действительно следует избегать.

решение2

Тебе нужно

eval "b=($a)"

evalоценит свой аргумент как команду оболочки после выполнения расширения параметра. Однако используйте с осторожностью. Убедитесь, что это $aне установлено пользовательским вводом, так как это может привести к разного рода проблемам.

Связанный контент