LINUX.ORG.RU

Ассоциативные массивы BASH4: как сделать присваивание?

 , ,


0

2

Не растекаясь мыслью по древу, вынужден констатировать, что взять и скопировать содержимое одного ассоциативного массива в другой у меня не получилось.
Не работают варианты:

declare -A H1 H2
H1=([A]=B [B]=C [C]=D)
H2=$H1
echo ${H2[@]}
# Пусто в H2, только не спит барсук
H2=(${H1[@]})
# Ошибка:
# bash: H2: B: must use subscript when assigning associative array
# bash: H2: C: must use subscript when assigning associative array
# bash: H2: D: must use subscript when assigning associative array
H2=${H1[@]}
echo ${H2[@]}
# H2[0] = "B, C, D", что легко доказывается так:
echo "1) ${!H2[@]}"
echo "2) ${H2[0]}"

Эмм... Хотел написать в русскую педивикию о присвоении массивов, да и мне самому в скрипте нужно, а оно... не работает, вообще никак. Неужели писать цикл - единственный выход для решения этой, вроде бы не слишком сложной задачи???

★★★★★

Последнее исправление: CYB3R (всего исправлений: 1)

Ох. там жесть

declare -A h1 h2

if [ -n ${!h1[@]} ]; then
 for name in ${!h1[@]}; do
   value="${h1[$name]}"
   h2[$name]="$value"
 done
fi

Как-то так

derlafff ★★★★★
()
Ответ на: комментарий от derlafff

Еще можно так, но тут есть масса подводных камней:

eval $(declare | grep ^oldarr= | sed -e 's/^oldarr/newarr/' ) #правда, не надо так делать

Так что да, только банальное копирование. Даже поручить это функции нельзя, ибо !, который используется для обращения к переменной по значению в переменной используется для получения ключей

derlafff ★★★★★
()
Последнее исправление: derlafff (всего исправлений: 1)
Ответ на: комментарий от derlafff

О передаче массивов в функции в качестве аргументов можно совсем забыть, да

derlafff ★★★★★
()
Ответ на: комментарий от derlafff

Да уж, это и правда жесть. Вот, в развёрнутом виде обсуждение нашей проблемы:
http://stackoverflow.com/questions/6660010/bash-how-to-assign-an-associative-...
В BASH как всегда: хотели подтянуться поближе к zsh, а реализовать по-человечески элементарный функционал не смогли.

DRVTiny ★★★★★
() автор топика

ну и зачем такое надо? Моё мнение, что если задача выходит за рамки «запустить программу и скормить её вывод другой программе», то вместо шелла берётся perl.

DELIRIUM ☆☆☆☆☆
()
Ответ на: комментарий от DELIRIUM

Perl всё-таки менее удобен для ползания по файловой системе и выполнения различных внешних команд. Да и по синтаксису сейчас в BASH есть много Perl'оподобного. Объективно, BASH в большинстве не мега-сложных случаев может не подходить под задачу только из-за его тормозов. Безусловно, программа на Perl в общем случае получается быстрее.

DRVTiny ★★★★★
() автор топика
Ответ на: комментарий от DRVTiny

Кстати, по теме. Сделать копию ассоциативного массива можно так:

declare -A H1=([AB]=CD [CD]=DE [DE]=EF)
t="$(declare -p H1)"
eval ${t/declare -A H1/declare -A H2}
На выходе получаем H2=H1 без всяких циклов.
Подозреваю, что метод работает плохо в случае объёмных хэш-массивов.

DRVTiny ★★★★★
() автор топика
Ответ на: комментарий от derlafff

declare -p даёт вывод аккурат-таки для eval'а, аккуратно расставляя одинарные кавычки, дабы чего лишнего не интерпретировалось.

DRVTiny ★★★★★
() автор топика
Ответ на: комментарий от DRVTiny

Perl всё-таки менее удобен для ползания по файловой системе

Не соглашусь. File::Find ничуть не хуже по возможностям и удобству, чем обычный find.

DELIRIUM ☆☆☆☆☆
()
Вы не можете добавлять комментарии в эту тему. Тема перемещена в архив.