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}_COLOURy 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 lafordeclaración. Usar solo$FRUITSes suficiente. Luego, puede eliminar una de las líneas dentro del bucle utilizandoeval.El
evalsimplemente 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
evalpara hacer eso:Tenga en cuenta el signo de dólar con barra invertida. Básicamente, la línea "eval" hace
bashque sustituya$fruity${fruit_color}, luego, useevalpara hacer una segunda ronda de sustitución antes de llamarecho.fuente
No necesita una declaración eval.
evales una pista en la mayoría de los idiomas de que estás haciendo algo mal.fuente
evalporque 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_prefixestá 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.