Когда у меня есть следующее:

a=foo
b=baz

Я могу использовать

typeset "$a=$b"

Но это не удается, если a ссылается на элемент массива:

$ a=foo[bar]
$ b=baz
$ typeset "$a=$b"
$ declare -p foo
declare -a foo=([0]="baz")

То есть по какой-то причине bar рассматривается как имя переменной. Любые идеи, как изменить это, чтобы я мог получить в результате declare -A foo=([bar]="baz"), желательно без разбора $a?

1
TJahns 15 Июл 2021 в 15:59

1 ответ

Лучший ответ

Вы никогда не объявляли foo как ассоциативный массив. Массивы и «скаляры» (из-за отсутствия лучшего слова для описания обычных переменных) никогда не нужно объявлять, но ассоциативные массивы делают это.

Поскольку вы не объявили foo как ассоциативный массив, ваш код устанавливает foo[0] в baz. Он устанавливает нулевой индекс, потому что bar используется в арифметическом контексте (поскольку это обычное присваивание массива). Ваша переменная bar, используемая в качестве индекса в обычном массиве, либо имеет нулевое значение, либо не установлена ​​(не существует).

Короче говоря, в операторе foo[bar]=baz нет ничего, что говорило бы о том, что foo является ассоциативным массивом. По умолчанию это будет обычный массив, а bar будет интерпретироваться в арифметическом контексте как некоторый целочисленный индекс (его значение будет равно нулю, если эта переменная не существует).

Чтобы получить то, что вы хотите, вам нужно будет объявить foo как ассоциативный массив.

a=foo[bar]
b=baz

declare -A foo

typeset "$a=$b"
declare -p foo

Это будет вывод

declare -A foo=([bar]="baz" )
2
Kusalananda 15 Июл 2021 в 16:49
Да, но основная проблема заключается в том, что из файла поступает целый набор пар (a,b), и я хотел рассматривать ассоциативные массивы так же, как и другие переменные, которые были установлены таким образом ранее.
 – 
TJahns
15 Июл 2021 в 16:36
2
Если бы вы могли описать общую проблему в своем вопросе, я мог бы сказать что-то об этом. Однако на данный момент все, что у меня есть, это «у меня это ..., и это не работает, почему и что делать?». Ассоциативные массивы должны быть объявлены перед назначением.
 – 
Kusalananda
15 Июл 2021 в 16:41
Обратите также внимание, что синтаксически в foo[bar]=baz нет ничего, что говорило бы о том, что foo является ассоциативным массивом, а не обычным массивом.
 – 
Kusalananda
15 Июл 2021 в 16:43
Я написал в исходном вопросе, что не хотел бы анализировать $a, если мне нужно условно выдать declare -A ${a%[*}, то, очевидно, это требует разбора. Я мог бы быть более точным в том, что $a и $b являются примерами, но я представил, что они являются переменными, что как-то проясняет проблему.
 – 
TJahns
15 Июл 2021 в 17:25
То, что вы хотите сделать, легче сделать с помощью чего-то вроде: declare -A foo; while read -r key value ; do foo["$key"]="$value"; done < file.txt; declare -p foo. Вам также может потребоваться установить переменную оболочки IFS в соответствии с форматом входного файла (например, если ваш ввод разделен чем-либо, кроме пробела)
 – 
cas
15 Июл 2021 в 17:56