2011-07-25 35 views
9

¿Puedo deshacerme de eval aquí? Estoy tratando de establecer $current_database con la variable apropiada determinada por la entrada del usuario (país y acción)variables de shell anidadas sin usar eval

# User input 
country="es" 
action="sales" 

# Possible variables for current_database 
final_es_sales_path="blahblah/es/sales.csv" 
final_en_support_path="yadayada/en/support.csv" 
final_it_inventory_path="humhum/it/inventory.csv" 
... 

current_database=$(eval echo \${final_${country}_${action}_path}) 
+1

Solo una nota: 'en',' es', 'it' son códigos de idioma ([ISO 639-1] (http://en.wikipedia.org/wiki/ISO_639)), no códigos de país. Los códigos de país ([ISO 3166-1] (http://en.wikipedia.org/wiki/ISO_3166-1)) se ven así: 'ES',' MX', 'GB',' US', 'IT' (para nombrar algunos países donde se hablan estos idiomas). –

Respuesta

9

Puede utilizar matrices asociativas, uniéndose el valor de ambas variables. Por ejemplo:

declare -A databases 
# initialization 
databases["es:sales"]="blahblah/es/sales.csv" 
databases["en:support"]="yadayada/en/support.csv" 

Entonces, se puede obtener la base de datos simplemente por:

echo ${databases["${country}:${action}"]} 

Esto tiene la ventaja de tener los nombres de bases de datos recogidos por una sola variable.

+0

Agradable. Así que puedo hacer: 'current_database = $ {databases [" $ {country}: $ {action} "]}'. Me pregunto si también hay una forma de hacerlo en Bash 3.x – nachocab

+0

una nota para la solución de problemas: si se olvida de hacer el 'declare -A' entonces la expansión siempre dará como resultado el último elemento que cree (en el código anterior , 'databases [" es: support "]' – Jeff

0

Does not

current_database=${final_${country}_${action}_path} 

hacer lo que quiera?

Editar: No, no es así. La expansión de parámetros solo funciona en una palabra (para el nombre del parámetro), y $ no está permitido en una palabra. Sin embargo, sería posible usar la expansión anidada de parámetros en las otras partes de las versiones más complicadas (con límites, reemplazo, valor predeterminado, etc.), por lo que las diversas variantes de expansión se enumeran aquí (lo que me engañó primero) (énfasis por mí):

Cuando se usan aparatos ortopédicos, la llave de poner fin a juego es el primer '}' no con una barra invertida o dentro de una cadena entre comillas, y no dentro de una expansión aritmética incrustado, sustitución de orden, o expansión de parámetro.

Lo sentimos. Parece que las matrices eval y arrays son tu mejor opción, entonces.

+0

No, es una mala sustitución. $ {final _ $ {country} _ $ {action} _path}: mala sustitución – nachocab

2

En realidad, sí puede, y sin recurrir a matrices asociativas (que no es una mala solución, tenga en cuenta). Puede utilizar una solución similar a esta:

> current_database=$(echo final_${country}_${action}_path) 
> echo $current_database 
final_es_sales_path 
> current_database=${!current_database} 
> echo $current_database 
blahblah/es/sales.csv 

Esto evita matrices y evaluaciones mediante el uso de la expansión indirecta. Esto parece haber sido introducido en la segunda versión de Bash, por lo que prácticamente cualquier máquina debería poder hacerlo.

+0

esto * es * igual de bueno - lástima que pueda no hay múltiples respuestas aceptadas – Jeff

Cuestiones relacionadas