it-swarm-es.com

$ VAR vs $ {VAR} y para cotizar o no cotizar

Puedo escribir

VAR=$VAR1
VAR=${VAR1}
VAR="$VAR1"
VAR="${VAR1}"

el resultado final para mí parece casi igual. ¿Por qué debería escribir uno u otro? ¿Alguno de estos no es portátil/POSIX?

150
xenoterracide

VAR=$VAR1 es una versión simplificada de VAR=${VAR1}. Hay cosas que el segundo puede hacer que el primero no puede, por ejemplo, hacer referencia a un índice de matriz (no portátil) o eliminar una subcadena (POSIX-portátil). Consulte la sección Más sobre variables de la Guía Bash para principiantes y Expansión de parámetros en la especificación POSIX.

Usando comillas alrededor de una variable como en rm -- "$VAR1" o rm -- "${VAR}" es una buena idea. Esto hace que el contenido de la variable sea una unidad atómica. Si el valor de la variable contiene espacios en blanco (bueno, los caracteres en el $IFS variable especial, espacios en blanco por defecto) o caracteres globales y no se cita, entonces cada palabra se considera para la generación de nombres de archivo (globalización) cuya expansión presenta tantos argumentos para lo que sea que esté haciendo.

$ find .
.
./*r*
./-rf
./another
./filename
./spaced filename
./another spaced filename
./another spaced filename/x
$ var='spaced filename'
# usually, 'spaced filename' would come from the output of some command and you weren't expecting it
$ rm $var
rm: cannot remove 'spaced': No such file or directory
# oops! I just ran 'rm spaced filename'
$ var='*r*'
$ rm $var
# expands to: 'rm' '-rf' '*r*' 'another spaced filename'

$ find .
.
./another
./spaced filename
./another spaced filename
$ var='another spaced filename'
$ rm -- "$var"
$ find .
.
./another
./spaced filename

Sobre portabilidad: de acuerdo con POSIX.1-2008 sección 2.6.2 , las llaves son opcionales.

108
Shawn J. Goff

${VAR} y $VAR son exactamente equivalentes. Para una expansión de variable simple, la única razón para usar ${VAR} es cuando el análisis de otra manera tomaría demasiados caracteres en el nombre de la variable, como en ${VAR1}_$VAR2 (que sin llaves sería equivalente a ${VAR1_}$VAR2). Expansiones más adornadas (${VAR:=default}, ${VAR#prefix}, ...) requieren llaves.

En una asignación variable, división de campo (es decir, división en el espacio en blanco en el valor) y expansión de nombre de ruta (es decir, globalización) se desactivan, por lo que VAR=$VAR1 es exactamente equivalente a VAR="$VAR1", en todos los shells POSIX y en todos los sh anteriores a POSIX de los que he oído hablar. (POSIX ref: comandos simples ). Por la misma razón, VAR=* establece de forma confiable VAR en la cadena literal *; por supuesto VAR=a b establece VAR en a ya que b es una palabra separada en primer lugar. En términos generales, las comillas dobles son innecesarias cuando la sintaxis de Shell espera una sola palabra, por ejemplo en case … in (pero no en el patrón), pero incluso allí debe tener cuidado: por ejemplo, POSIX especifica que objetivos de redirección (>$filename) no requieren comillas en los scripts, pero algunos shells incluyendo bash requieren comillas dobles incluso en scripts. Vea ¿Cuándo es necesaria una doble cita? para un análisis más completo.

Necesita las comillas dobles en otros casos, en particular en export VAR="${VAR1}" (que se puede escribir de manera equivalente export "VAR=${VAR1}") en muchos shells (POSIX deja este caso abierto). La similitud de este caso con asignaciones simples, y la naturaleza dispersa de la lista de casos en los que no necesita comillas dobles, es por eso que recomiendo usar comillas dobles a menos que desee dividir y englobar.

Cotización

Considere que la comilla doble se usa para la expansión variable, y la comilla simple se usa para las comillas fuertes, es decir, sin expansión.

Expansión:

this='foo'
that='bar'
these="$this"
those='$that'

Salida:

for item in "$this" "$that" "$these" "$those"; do echo "$item"; done
foo
bar
foo
$that

Puede valer la pena mencionar que debe usar la cita siempre que sea posible por varias razones, entre las cuales se considera la mejor práctica y la legibilidad. También porque Bash es peculiar a veces y a menudo por formas aparentemente ilógicas o irrazonables/inesperadas, y la cita cambia las expectativas implícitas a explícitas, lo que reduce esa superficie de error (o potencial para ello).

Y si bien es completamente legal no cotizar, y funcionará en la mayoría de los casos, esa funcionalidad se proporciona por conveniencia y probablemente sea menos portátil. La práctica totalmente formal garantizada para reflejar la intención y la expectativa es citar.

Sustitución

Ahora considere también que la construcción "${somevar}" se utiliza para operaciones de sustitución. Varios casos de uso, como reemplazo y matrices.

Reemplazo (pelado):

thisfile='foobar.txt.bak'
foo="${thisfile%.*}"   # removes shortest part of value in $thisfile matching after '%' from righthand side
bar="${thisfile%%.*}"  # removes longest matching

for item in "$foo" "$bar"; do echo "$item"; done
foobar.txt
foobar

Reemplazo (reemplazo):

foobar='Simplest, least effective, least powerful'
# ${var/find/replace_with}
foo="${foobar/least/most}"   #single occurrence
bar="${foobar//least/most}"  #global occurrence (all)

for item in "$foobar" "$foo" "$bar"; do echo "$item"; done
Simplest, least effective, least powerful
Simplest, most effective, least powerful
Simplest, most effective, most powerful

Matrices:

mkdir temp
# create files foo.txt, bar.txt, foobar.txt in temp folder
touch temp/{foo,bar,foobar}.txt
# alpha is array of output from ls  
alpha=($(ls temp/*))

echo "$alpha"         #  temp/foo.txt
echo "${alpha}"       #  temp/foo.txt
echo "${alpha[@]}"    #  temp/bar.txt  temp/foobar.txt  temp/foo.txt
echo "${#alpha}"      #  12 # length of first element (implicit index [0])
echo "${#alpha[@]}"   #  3  # number of elements
echo "${alpha[1]}"    #  temp/foobar.txt # second element
echo "${#alpha[1])"   #  15 # length of second element

for item in "${alpha[@]}"; do echo "$item"; done
temp/bar.txt
temp/foobar.txt
temp/foo.txt

Todo esto apenas está rascando la superficie de la "${var}" construcción de sustitución. La referencia definitiva para las secuencias de comandos de Bash Shell es la referencia en línea libre, TLDP The Linux Documentation Project https://www.tldp.org/LDP/abs/html/parameter-substitution.html

9
SYANiDE
ls -la

lrwxrwxrwx.  1 root root      31 Nov 17 13:13 prodhostname
lrwxrwxrwx.  1 root root      33 Nov 17 13:13 testhostname
lrwxrwxrwx.  1 root root      32 Nov 17 13:13 justname

termina entonces:

env=$1
    if [ ! -f /dirname/${env}hostname ]

vale la pena mencionar como un ejemplo más claro del uso de curvas

0
ninjabber