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 $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.
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:
$ var="foo *"ser así $ foo="foo *". No lo usas en varningún lado.
$al final! Se tratará como un carácter normal y no como parte del nombre de la variable.