Asignación de variables indirectas en bash

Resuelto Eli Barzilay asked hace 12 años • 7 respuestas

Parece que la forma recomendada de realizar la configuración de variables indirectas en bash es usar eval:

var=x; val=foo
eval $var=$val
echo $x  # --> foo

El problema es el habitual con eval:

var=x; val=1$'\n'pwd
eval $var=$val  # bad output here

(y dado que se recomienda en muchos lugares, me pregunto cuántos scripts son vulnerables debido a esto...)

En cualquier caso, la solución obvia de usar comillas (de escape) realmente no funciona:

var=x; val=1\"$'\n'pwd\"
eval $var=\"$val\"  # fail with the above

La cuestión es que bash tiene una referencia de variable indirecta integrada (con ${!foo}), pero no veo ninguna forma de realizar una asignación indirecta. ¿Existe alguna forma sensata de hacer esto?

Para que conste, encontré una solución, pero esto no es algo que yo consideraría "sano"...:

eval "$var='"${val//\'/\'\"\'\"\'}"'"
Eli Barzilay avatar Mar 30 '12 14:03 Eli Barzilay
Aceptado

Bash tiene una extensión printfque guarda su resultado en una variable:

printf -v "${VARNAME}" '%s' "${VALUE}"

Esto evita todos los posibles problemas de escape.

Si utiliza un identificador no válido para $VARNAME, el comando fallará y devolverá el código de estado 2:

$ printf -v ';;;' '%s' foobar; echo $?
bash: printf: `;;;': not a valid identifier
2
David Foerster avatar Jun 06 '2013 23:06 David Foerster

Una forma ligeramente mejor, evitando las posibles implicaciones de seguridad del uso eval, es

declare "$var=$val"

Tenga en cuenta que declarees sinónimo de typeseten bash. El typesetcomando es más ampliamente compatible ( kshy zshtambién úselo):

typeset "$var=$val"

En las versiones modernas de bash, se debe utilizar un nameref.

declare -n var=x
x=$val

Es más seguro que eval, pero aún no es perfecto.

chepner avatar Jul 12 '2012 20:07 chepner