Bash-скриптинг - перебор "переменных" имен переменных для списка ассоциативных массивов

У меня есть список переменных ассоциативных массивов, которые я хочу перебрать и получить их пары ключ / значение.

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

for key in "${!queue1[@]}" do
    echo "key : $key"
    echo "value : ${queue1[$key]}"
done

Сложность заключается в том, что имена ассоциативных массивов являются переменными переменными, например, учитывая count = 5, ассоциативные массивы будут называться queue1, queue2, queue3, queue4, queue5.

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

for count in {1,2,3,4,5} do
    for key in "${!queue${count}[@]}" do
        echo "key : $key"
        echo "value : ${queue${count}[$key]}"
    done
done

Помощь будет очень ценится!

3 ответа

Решение

Трудность здесь связана с тем, что синтаксис для косвенного расширения (${!nameref}) конфликтует с синтаксисом извлечения ключей из ассоциативных массивов (${!array[@]}). Мы можем иметь только одно или другое, но не оба.

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

keyref="queue${count}[@]"
for key in $(eval echo '${!'$keyref'}'); do ... ; done

Однако вы можете избежать eval и использовать косвенное расширение при извлечении значения из массива с заданным ключом. Обратите внимание, что [key] суффикс должен быть частью расширения:

valref="queue${count}[$key]"
echo ${!valref}

Чтобы поместить это в контекст:

for count in {1..5} ; do
    keyref="queue${count}[@]"
    for key in $(eval echo '${!'$keyref'}'); do
        valref="queue${count}[$key]"
        echo "key = $key"
        echo "value = ${!valref}"
    done
done

Я смог заставить его работать со следующим скриптом:

for count in {1..5} ; do
    for key in $(eval echo '${!q'$count'[@]}') ; do
        eval echo '${q'$count"[$key]}"
    done
done

Обратите внимание, что он ломается, если какой-либо ключ содержит пробел. Если вы хотите иметь дело со сложными структурами данных, используйте более мощный язык, такой как Perl.

Я думаю, что это может работать (но не проверено). Ключ должен относиться к индексации как к полному имени переменной. (То есть массив queue5 может рассматриваться как последовательность переменных с именем queue5[this], queue5[that], так далее.)

for count in {1,2,3,4,5} do
    assoc="queue$count[@]"
    for key in "${!assoc}" do
        echo "key : $key"
        val="queue$count[$key]"
        echo "value : ${!val}"
    done
done
Другие вопросы по тегам