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

puedo escribir

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

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

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 reference a un índice de matriz (no portátil) o eliminar una subcadena (POSIX-portable). Consulte la sección Más sobre variables de la Guía Bash para principiantes y expansión de parameters en la especificación POSIX.

Usar comillas alnetworkingedor de una variable como en rm -- "$VAR1" o rm -- "${VAR}" es una buena idea. Esto hace que los contenidos de la variable sean una unidad atómica. Si el valor de la variable contiene espacios en blanco (bien, caracteres en la variable especial $IFS , espacios en blanco por defecto) o caracteres globbing y no lo cite, entonces se considera cada palabra para generación de nombre de file (globbing) cuya expansión hace tantos arguments para lo que sea que estés 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 

En portabilidad: según POSIX.1-2008 sección 2.6.2 , las llaves son opcionales.

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

En una asignación de variable, la split de campo (es decir, split en espacios en blanco en el valor) y la expansión del nombre de ruta (es decir, globbing) se desactivan, por lo que VAR=$VAR1 es exactamente equivalente a VAR="$VAR1" en todas las shells POSIX y en todos pre-POSIX sh de lo que he oído hablar. (Ref POSIX: commands simples ). Por la misma razón, VAR=* establece confiablemente VAR a la cadena literal * ; por supuesto, VAR=ab establece VAR a, ya que b es una palabra separada en primer lugar. En general, las comillas dobles son innecesarias cuando la syntax del shell espera una sola palabra, por ejemplo en case … in (pero no en el patrón), pero incluso allí hay que tener cuidado: por ejemplo, POSIX especifica que los destinos de networkingirección ( >$filename ) no requieren citar en scripts, pero algunas shells incluyendo bash requieren las comillas dobles incluso en scripts. Ver ¿ Cuándo es doble la cita necesaria? para un análisis más completo.

Sí necesita las comillas dobles en otros casos, en particular en export VAR="${VAR1}" (que puede escribirse de forma equivalente export "VAR=${VAR1}" ) en muchos shells (POSIX deja este caso abierto). La similitud de este caso con las asignaciones simples y la naturaleza dispersa de la list de casos en los que no se necesitan comillas dobles, son las razones por las que recomiendo el uso de comillas dobles a less que desee dividir y englobar.

 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 

finaliza entonces:

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

vale la pena mencionarlo como un ejemplo más claro del uso de curlies