¿Qué es la expansión indirecta? ¿Qué significa $ {! Var *}?


85

Estoy leyendo " Guía de Bash para principiantes ". Dice:

Si el primer carácter de PARAMETERes un signo de exclamación, Bash usa el valor de la variable formada a partir del resto de PARAMETERcomo el nombre de la variable; esta variable luego se expande y ese valor se usa en el resto de la sustitución, en lugar del valor de PARAMETERsí mismo. Esto se conoce como expansión indirecta.

El ejemplo dado es:

franky ~> echo ${!N*}
NNTPPORT NNTPSERVER NPX_PLUGIN_PATH

No entiendo bien aquí:

el valor de la variable formada por el resto de PARAMETER

Como PARAMETERes justo !N*, entonces

el resto de PARAMETER

es justo N*. ¿Cómo podría esto formar una variable? ¿Bash buscó todos los comandos posibles allí?

Respuestas:


110

Si lee la bashpágina del manual, básicamente confirma lo que ha dicho:

Si el primer carácter del parámetro es un signo de exclamación ( !), se introduce un nivel de direccionamiento indirecto variable. Bash usa el valor de la variable formada a partir del resto del parámetro como el nombre de la variable; esta variable luego se expande y ese valor se usa en el resto de la sustitución, en lugar del valor del parámetro en sí. Esto se conoce como expansión indirecta.

Sin embargo, leyendo desde allí:

Las excepciones a esto son las expansiones de ${!prefix*}y se ${!name[@]}describen a continuación.

${!prefix*}Nombres coincidentes con prefijo. Se expande a los nombres de las variables cuyos nombres comienzan con prefijo, separados por el primer carácter de la IFSvariable especial.

En otras palabras, su ejemplo particular ${!N*}es una excepción a la regla que citó. Se hace , sin embargo, funcionan como se anuncia en los casos previstos, tales como:

$ export xyzzy=plugh ; export plugh=cave

$ echo ${xyzzy}  # normal, xyzzy to plugh
plugh

$ echo ${!xyzzy} # indirection, xyzzy to plugh to cave
cave

1
Gracias por la respuesta. Cuanto más leo la "Guía de Bash para principiantes", más me pregunto si la autora comprende lo que escribe.
— LRDPRDX

23

Parece haber una excepción cuando la "indirección" dada termina en a *, como ocurre aquí. En este caso, da todos los nombres de variables que comienzan con la parte que especificó ( Naquí). Bash puede hacer eso porque rastrea las variables y sabe cuáles existen.

La verdadera indirección es la siguiente:
digamos que tengo una variable $VARIABLEestablecida en 42y tengo otra variable $NAMEestablecida en VARIABLE. ${!NAME}me dará 42. Utiliza el valor de una variable para decirle el nombre de otra:

$ NAME="VARIABLE"
$ VARIABLE=42
$ echo ${!NAME}
42

5
¡Vaya, quién diría que era tan fácil obtener la respuesta al significado de la vida, el universo y todo!
— KomodoDave

3

Sí, busca todas las posibles expansiones de variables después de!. Si lo hubiera hecho:

echo ${!NP*}

solo obtendrías NPX_PLUGIN_PATH .

Considere el siguiente ejemplo:

:~> export myVar="hi"
:~> echo ${!my*}
    myVar
:~> export ${!my*}="bye"
:~> echo $myVar
    bye

¿otras variables que coincidan con mi * también se establecerían en "bye"?
— Anthony

1
@Anthony Lo probé, y si se ${!my*}expande a myA, myB, myA se exporta con su valor actual y myB se establece en "bye" y se exporta. No es muy útil.
— GKFX

3

Ha encontrado una excepción en el procesamiento indirecto, donde si el último carácter es *, se devolverán todas las variables que tienen el prefijo dado antes.


Entonces, aparte del *caso, ¿es esto lo mismo que ${${VAR}}?
— chronospoon

1
@chronospoon, ${${VAR}}más brevemente escribible como ${$VAR}, no es legal, ya que $VARdevuelve una cadena, que no puede seguir el $signo; para usar una cadena como nombre de variable, debe introducir un nivel de direccionamiento indirecto (como se cita en la pregunta original), es decir , puede usar ${!VAR}, que hace exactamente lo que esperaría (errónea pero comprensiblemente) ${$VAR}.
— Enrico

Al usar nuestro sitio, usted reconoce que ha leído y comprende nuestra Política de Cookies y Política de Privacidad.
Licensed under cc by-sa 3.0 with attribution required.