Puedo hacer esto, pero requiere hacer una cadena de la variable y luego desreferenciarla. ¿Hay alguna forma de acortarlo a una declaración más simple?
#!/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
He intentado muchas cosas como ${!"${fruit}_COLOUR"}
o \$${fruit}_COLOUR
y muchas otras variantes, pero la única forma en que ha funcionado es usando una cadena.
bash
variable-substitution
Estera
fuente
fuente
!
sintaxis es un indicador de sustitución de variables que básicamente dice "sustituir dos veces". No cambia el requisito de que lo que hay dentro${…}
debe ser un nombre de variable. Entonces, no, no puede evitar usar una variable que contenga el nombre, a menos que use un método diferente (eval
).Respuestas:
En primer lugar, no necesita usar
$(echo $FRUITS)
en lafor
declaración. Usar solo$FRUITS
es suficiente. Luego, puede eliminar una de las líneas dentro del bucle utilizandoeval
.El
eval
simplemente le dice a bash para realizar una segunda evaluación de la siguiente declaración (es decir, uno más que su evaluación normal). La\$
sobrevive a la primera evaluación,$
y la próxima evaluación a continuación, trata a este$
como el inicio de un nombre de variable, que se resuelve a "Amarillo", etc.De esta manera, no necesita tener un paso separado que haga una cadena provisional (que es lo que creo que fue la intención principal de su pregunta).
Para un método alternativo, como mencionó Patrick en un comentario (arriba), puede usar una matriz asociativa , en la que el índice de un elemento no necesita ser un número entero. Puede usar una cadena, como el nombre de un tipo de fruta. Aquí hay un ejemplo, usando la matriz asociativa de bash:
fuente
Puede usar bash-builtin
eval
para hacer eso:Tenga en cuenta el signo de dólar con barra invertida. Básicamente, la línea "eval" hace
bash
que sustituya$fruit
y${fruit_color}
, luego, useeval
para hacer una segunda ronda de sustitución antes de llamarecho
.fuente
No necesita una declaración eval.
eval
es una pista en la mayoría de los idiomas de que estás haciendo algo mal.fuente
eval
porque al menos las personas saben que es peligroso,${!var}
es casi tan peligrosobash
(también es una vulnerabilidad de inyección de comando si$chosen_prefix
está bajo el control de un atacante) y menos personas lo saben. Tratarvar_name='a[$(uname>&2)0]' bash -c 'v=${!var_name}'
. El mejor enfoque aquí es la matriz asociativa.