Я могу сделать это, но для этого нужно создать строку переменной, а затем разыменовать ее. Есть ли способ сократить это до более простого утверждения?
#!/bin/bash
FRUITS="BANANA APPLE ORANGE"
BANANA_COLOUR="Yellow"
APPLE_COLOUR="Green or Red"
ORANGE_COLOUR="Blue"
for fruit in $( echo $FRUITS ); do
fruit_colour="${fruit}_COLOUR"
echo $fruit is ${!fruit_colour}
done
Я перепробовал множество вещей, таких как ${!"${fruit}_COLOUR"}
или \$${fruit}_COLOUR
и многие другие варианты, но единственный способ, который сработал, - это использование строки.
!
Синтаксис флаг на переменную подстановки, в основном говорит «заменить дважды». Это не меняет требования, что внутри${…}
должно быть имя переменной. Поэтому нет, вы не можете избежать использования переменной, содержащей имя, если вы не используете другой метод (eval
).Ответы:
Во-первых, вам не нужно использовать
$(echo $FRUITS)
вfor
заявлении. Использование только$FRUITS
достаточно. Затем вы можете покончить с одной из строк внутри цикла, используяeval
.eval
Просто говорит Баш , чтобы сделать вторую оценку следующего утверждения (то есть более чем одна его нормальная оценка). При\$
первой оценке сохраняется как$
, а при следующей оценке это рассматривается$
как начало имени переменной, которая преобразуется в «Желтый» и т. Д.Таким образом, вам не нужно иметь отдельный шаг, который составляет промежуточную строку (что, как я считаю, было основной целью вашего вопроса).
Для альтернативного метода, как упомянуто Патриком в комментарии (выше), вместо этого вы можете использовать ассоциативный массив , в котором индекс элемента не обязательно должен быть целым числом. Вы можете использовать строку, например, название типа фруктов. Вот пример использования ассоциативного массива bash:
источник
Вы можете использовать bash-buildin
eval
для этого:Обратите внимание на знак доллара с обратной косой чертой. По сути, строка «eval» приводит
bash
к замене$fruit
и${fruit_color}
затем использованиюeval
второго раунда подстановки перед вызовомecho
.источник
Вам не нужно утверждение Eval.
eval
Подсказка в большинстве языков, что вы делаете что-то не так.источник
eval
потому что, по крайней мере, люди знают, что это опасно,${!var}
примерно так же опасноbash
(также уязвимость внедрения команд, если$chosen_prefix
находится под контролем злоумышленника), и меньше людей знают об этом. Попробуйvar_name='a[$(uname>&2)0]' bash -c 'v=${!var_name}'
. Лучший подход здесь - ассоциативный массив.