Hacer referencia a variables en un script de shell


10

En un script de shell, si defino una variable como FOO=25, ¿hay alguna diferencia entre hacer referencia a ella como $FOO$y ${FOO}$?


2
¡No debes usar el $al final! Se tratará como un carácter normal y no como parte del nombre de la variable.
Byte Commander

Respuestas:


16

En la mayoría de situaciones tanto $vary ${var}son los mismos. (¡Tenga en cuenta que no debe usar $a al final!)

Un ejemplo en el que necesita llaves es cuando necesita poner una variable en una cadena continua.

Ejemplo:

var=hel
echo ${var}lo

es la salida hello.


11

Para responder a su pregunta principal, ${foo}se llama "expansión de parámetros" . Para ser precisos, el $mismo inicia la expansión de parámetros, en { }realidad son opcionales según la especificación POSIX , pero pueden ser útiles para indicar el final del nombre de la variable:

$ foo="bar"
$ echo $fooBaz   ## fails, no variable named $fooBaz exists

$ echo ${foo}Baz ## works, $foo is expanded and the string Baz is appended
barBaz

Básicamente, $fooy ${foo}son idénticos. Además de casos como el anterior o cuando está haciendo manipulación de cadenas , son completamente equivalentes.

Sin embargo, no deberías usar ninguno de ellos. La regla general es que, con muy pocas excepciones, siempre debe usar "$foo"o "${foo}"y nunca $fooo ${foo}. Siempre debe citar sus variables para evitar invocar al operador split + glob (más sobre eso más adelante). Ciertamente no quieres $foo$. La final $es irrelevante:

$ foo="bar"
$ echo "$foo$"
bar$

Entonces, aunque las variables sin comillas a veces están bien:

$ echo $foo
bar

Por lo general, no lo son y realmente deberían evitarse:

$ if [ -n $foo ]; then echo empty; else echo "not empty"; fi ## fails
empty

$ if [ -n "$foo" ]; then echo empty; else echo "not empty"; fi ## works
not empty

Tenga en cuenta que los corchetes tampoco ayudan aquí:

$ if [ -n ${foo} ]; then echo empty; else echo "not empty"; fi  ## fails
empty

$ if [ -n "${foo}" ]; then echo empty; else echo "not empty"; fi ## works
not empty

Cuando usa $fooo ${foo}, el shell dividirá el valor guardado en la variable en el espacio en blanco (esto se puede cambiar configurando la IFSvariable a otra cosa) en una lista y luego, cada elemento de la lista se trata como un patrón global y se expande en cualquier archivo o directorio que coincida. Esto se conoce como el operador split + glob . Para ilustrar, considere un directorio con dos archivos:

$ ls -l
-rw-r--r-- 1 terdon terdon 0 Oct  9 18:16 file1
-rw-r--r-- 1 terdon terdon 0 Oct  9 18:16 file2

Ahora, configuremos una variable para foo *:

$ foo="foo *"

¿Qué sucede si intentamos verificar si existe un archivo con ese nombre?

$ if [ -e $foo ]; then echo "file exists"; else echo "no such file"; fi
file exists

La variable se dividió en fooy *, y dado que *es un comodín que coincide con cualquier cadena, el shell le dice que foo *existe un archivo llamado exxists. Sin embargo, si lo citamos correctamente, esto no sucede:

$ if [ -e "$foo" ]; then echo "file exists"; else echo "no such file"; fi
no such file

Ese fue un ejemplo trivial para ilustrar el punto. Imagínese si hubiera usado en rmlugar de echosin embargo.

Entonces, primera regla: siempre cita tus variables. Puede usar cualquiera "$foo"o "${foo}"pero citarlo de cualquier manera. Para obtener más detalles sobre el uso seguro de variables, eche un vistazo a estas publicaciones:


No quería editar su excelente respuesta, pero no debería $ var="foo *"ser así $ foo="foo *". No lo usas en varningún lado.
Joe

@ Joe, ¡qué pena! Sí, por supuesto que debería, gracias por señalarlo. Por cierto, siéntase libre de corregir tales errores sugiriendo una edición. Se recomienda mucho ese tipo de cosas, precisamente para evitar errores tontos como este.
terdon
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.