Eu posso fazer isso, mas é necessário criar uma sequência da variável e desreferencia-la. Existe alguma maneira de encurtar para uma declaração mais simples?
#!/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
Eu tentei muitas coisas como ${!"${fruit}_COLOUR"}
ou \$${fruit}_COLOUR
e muitas outras variantes, mas a única maneira que funcionou é usando uma string.
bash
variable-substitution
Esteira
fonte
fonte
!
sintaxe é um sinalizador na substituição de variável que basicamente diz "substituir duas vezes". Não altera o requisito de que o conteúdo esteja dentro do${…}
nome da variável. Portanto, não, você não pode evitar o uso de uma variável que contém o nome, a menos que use um método diferente (eval
).Respostas:
Primeiro, você não precisa usar
$(echo $FRUITS)
afor
declaração. Usar apenas$FRUITS
é suficiente. Então você pode acabar com uma das linhas dentro do loop, usandoeval
.O
eval
simplesmente diz ao bash para fazer uma segunda avaliação da seguinte declaração (ou seja, uma a mais que a sua avaliação normal). Ele\$
sobrevive à primeira avaliação como$
e a próxima avaliação trata isso$
como o início de um nome de variável, que resolve como "Amarelo" etc.Dessa forma, você não precisa ter uma etapa separada que faça uma sequência intermediária (que é o que acredito ser a principal intenção da sua pergunta).
Para um método alternativo, como mencionado por Patrick em um comentário (acima), você pode usar uma matriz associativa , na qual o índice de um elemento não precisa ser um número inteiro. Você pode usar uma sequência, como o nome de um tipo de fruta. Aqui está um exemplo, usando a matriz associativa do bash:
fonte
Você pode usar o bash-builtin
eval
para fazer isso:Observe o sinal de dólar com barra invertida. Basicamente, a linha "eval" faz
bash
com que substitua$fruit
e${fruit_color}
, em seguida, useeval
para fazer uma segunda rodada de subestação antes de chamarecho
.fonte
Você não precisa de uma declaração de avaliação.
eval
é uma dica na maioria dos idiomas de que você está fazendo algo errado.fonte
eval
porque pelo menos as pessoas sabem que é perigoso,${!var}
é quase tão perigoso quantobash
(também uma vulnerabilidade de injeção de comando se$chosen_prefix
estiver sob o controle de um invasor) e menos pessoas estão cientes disso. Tentevar_name='a[$(uname>&2)0]' bash -c 'v=${!var_name}'
. A melhor abordagem aqui é a matriz associativa.