2009-11-07 8 views
10

Digamos que tengo el nombre de una variable almacenada en otra variable:variables de shell de búsqueda por nombre, indirectamente

myvar=123 
varname=myvar 

ahora, me gustaría llegar 123 sólo por el uso variable $ varname. ¿Hay una forma directa de hacerlo? He encontrado hay tal fiesta orden interna para la búsqueda por nombre, por lo que se le ocurrió esto:

function var { v="\$$1"; eval "echo "$v; } 

por lo

var $varname # gives 123 

Lo que no se ve tan mal al final, pero me pregunto si yo se perdió algo más obvio. ¡Gracias por adelantado!

+0

Esto se marca como un duplicado de una pregunta que se hizo 6 años después? También en mi humilde opinión esta pregunta + respuestas es más clara que las vinculadas. – inger

Respuesta

12

Desde el man page of bash:

${!varname} 

Si el primer carácter del parámetro es un signo de exclamación, se introduce un nivel de indirección 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 es conocido como expansión indirecta.

+0

Por supuesto, eso es todo. Ha intentado con RTFM, pero de alguna manera esta descripción: ----------------- $ {! Prefix *} $ {! Prefix @} Prefijo de coincidencia de nombres. Se expande a los nombres de las variables cuyos nombres comienzan con el prefijo, separados por el primer carácter de la variable especial IFS . Cuando se usa @ y la expansión aparece entre comillas dobles, cada nombre de variable se expande a una palabra separada. ----------------- no me pareció la respuesta obvia. ¡Saludos por eso! – inger

+0

@DigitalRoss: la pregunta fue etiquetada con "bash", entonces, ¿por qué quieres restringir la respuesta al estándar posix? – tangens

+1

Es una buena respuesta, y sí se aplica a bash. Supongo que la respuesta perfecta sería anunciar '$ {! Varname}' y luego notar el problema de portabilidad para evitar que la OP tenga posibles problemas. – DigitalRoss

12

No hay una sintaxis de conformado directo de Posix, solo un bash ismo. Yo suelo hacer esto:

eval t="\$$varname" 

Esto funcionará en cualquier shell POSIX, incluyendo aquellos sistemas en los bash es el shell de entrada y /bin/sh es algo más pequeño y más rápido como ash. Me gusta bash y lo uso para mi shell de inicio de sesión pero evito los bashisms en los archivos de comando.


Nota: Un problema con la escritura de scripts específicos de bash es que, incluso si puede contar con la instalación de bash, podría estar en cualquier parte de la ruta. En ese caso, podría ser una buena idea utilizar el estilo /usr/bin/envshebang completamente general, pero tenga en cuenta que todavía no es 100% portátil y tiene problemas de seguridad.

+0

Según el contexto en el que necesite el valor, puede usar '$ (eval \ $$ varname)' en lugar de una asignación. –

+0

Intenté casi eso, pero lo perdí. Más corto que el mío, ¡gracias por eso! – inger

+0

no es '$ (....)' no-posix? ¿No debería ser '\' eval \ $$ varname' \ 'en su lugar? –

1

${!varname} debe hacer el truco

$ var="content" 
$ myvar=var 
$ echo ${!myvar} 
content 
+0

Gracias, parece que tu respuesta llegó un momento después que los tangentes, así que seleccioné esa :) – inger

1

lo general miro Advance Bash-Scripting Guide cuando necesito para refrescar mis conocimientos del golpe.

En cuanto a su aspecto cuestión en Indirect References

notación es:

Version < 2 
\$$var 

Version >= 2 
${!varname} 
+0

Hmm, eché un vistazo rápido a esa guía, aparentemente demasiado rápido :) Parece que tengo que leerla correctamente ... gracias por la sugerencia ! – inger

+0

Es mi referencia rápida de elección, tiendo a usarla con más frecuencia que las páginas man. Pero como dices, un vistazo rápido a veces no es suficiente. –

+0

En general, el ABS debe tomarse con un gran grano de sal. Sin embargo, nada malo con esta respuesta per se. – tripleee

0
# bmuSetIndirectVar() 
# TO DOUBLE CHECK THIS COMMENT AND DEMO 
# This function is an helper to read indirect variables. 
# i.e. get the content of a variable whose name is saved 
# within an other variable. Like: 
# MYDIR="/tmp" 
# WHICHDIR="MYDIR" 
#  bmuSetIndirectVar "WHICHDIR" "$MYDIR" 
# 
bmuSetIndirectVar(){ 
    tmpVarName=$1 
    locVarName=$1 
    extVarName=$2 
    #echo "debug Ind Input >$1< >$2<" 
    eval tmpVarName=\$$extVarName 
    #echo "debug Ind Output >$tmpVarName< >$extVarName<" 
    export $locVarName="${tmpVarName}" 
} 

Actualmente estoy usando esta pequeña función. No estoy completamente satisfecho con él, y he visto diferentes soluciones en la web (si pudiera recordar que las escribiría aquí), pero parece funcionar. Dentro de estas pocas líneas ya hay algo de redundancia y datos adicionales, pero fue útil para la depuración.

Si usted quiere ver en su sitio, es decir, cuando lo estoy usando, verificar: https://github.com/mariotti/bmu/blob/master/bin/backmeup.shellfunctions.sh

Por supuesto que no es la mejor solución, pero me hizo ir adelante con el trabajo, en la esperanza Puedo reemplazarlo con algo un poco más general pronto.

+0

Antes de las preguntas;) Lo que no me gusta de esta función es que utilizo un "eval" que típicamente es un desencadenante del mal diseño. Por supuesto, hay lugares donde lo necesitas. Lo que me gusta es que al usar una función puedo separar el código del problema y optimizarlo más adelante. Tal vez incluso introducir un control de versión de shell o similar. – mariotti

Cuestiones relacionadas