En un script de shell, si defino una variable como FOO=25
, ¿hay alguna diferencia entre hacer referencia a ella como $FOO$
y ${FOO}$
?
En un script de shell, si defino una variable como FOO=25
, ¿hay alguna diferencia entre hacer referencia a ella como $FOO$
y ${FOO}$
?
Respuestas:
En la mayoría de situaciones tanto $var
y ${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
.
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, $foo
y ${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 $foo
o ${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 $foo
o ${foo}
, el shell dividirá el valor guardado en la variable en el espacio en blanco (esto se puede cambiar configurando la IFS
variable 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 foo
y *
, 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 rm
lugar de echo
sin 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:
$ var="foo *"
ser así $ foo="foo *"
. No lo usas en var
ningún lado.
$
al final! Se tratará como un carácter normal y no como parte del nombre de la variable.