Asignacion de variables en Bash

En Bash, ¿qué diferencia hay entre las siguientes tres instrucciones?

  • VARIABLE=valor instrucción
  • VARIABLE=valor; instrucción
  • export VARIABLE=valor; instrucción

¿Por qué no todas las combinaciones funcionan cuando se invoca Make y por qué no todas las combinaciones funcionan con echo?

Asignar una variable puede afectar a una de dos: al ambiente o a las variables del shell. Pero ¿cuál afecta a cuál? Para acabar de complicar la situación, en algunos casos es un cambio persistente y en otros es un cambio temporal.

Para salir de la duda de una vez por todas y entender con exactitud lo que ocurre, he preparado una dupla de pruebas para cada una de las 3 sintaxis, resultando en 6 combinaciones:

  1. VAR=val env | grep VAR; env | grep VAR
  2. VAR=val; env | grep VAR; env | grep VAR
  3. export VAR=val; env | grep VAR; env | grep VAR
  4. VAR=val echo $VAR; echo $VAR
  5. VAR=val; echo $VAR; echo $VAR
  6. export VAR=val; echo $VAR; echo $VAR

Estas pruebas deberían ser suficientes para salir de la duda. Para asegurar la fiabilidad a las pruebas, cada una la envolví de esta forma, que permitirá, incluso, ver los saltos de línea:

(unset VAR; PRUEBA) | tr '\n' :; echo

Resultados:

VAR=val instr VAR=val; instr export VAR=val; instr
echo $VAR; echo $VAR :: val:val: val:val:
env | grep VAR; env | grep VAR VAR=val: (línea vacía) VAR=val:VAR=val:

Se concluye lo siguiente:

VAR=val instr VAR=val; instr export VAR=val; instr
Alcance Sólo para la instrucción especificada A partir de este momento A partr de este momento
Ambiente al que afecta Subproceso Shell actual Shell actual y subproceso

Tiene sentido:

En la sintaxis VAR=val instr, la asignación es un prefijo para instr y sólo para instr. Lo interesante es que sólo afecta al ambiente exportado a la instrucción. Es decir, VAR=val echo $VAR no funciona porque la variable la expande Bash mismo antes de asignar el valor val a VAR. En efecto: VAR=val1; VAR=val2 echo $VAR regresa val1.

En la sintaxis VAR=val; instr, el punto y coma efectivamente separa una instrucción de la otra. Es el equivalente de asignar el valor val a VAR antes que cualquier otra instrucción como una acción independiente; es una acción independiente. Esto le da la persistencia del valor tanto en esta sinaxis como en la tercera. Además, Bash, por defecto, no exporta sus variables al entorno. Esto hace que sólo se afecte la instrucción echo… O bueno… en realidad no, no es echo quien se está viendo afectado. Ojo: Echo no recibe la variable en su entorno: es Bash quien está expandiendo la variable a su valor al llamar echo, quien recibe el valor ya expandido como argumento.

La tercera sintaxis, export VAR=val; instr es igual a la segunda: dos instrucciones independientes, con la adición de que la instrucción export, naturalmente interna a Bash, indica que VAR se debe exportar al ambiente de los siguientes subprocesos. Es decir, tanto se asigna como se importa en la misma instrucción. Es por esto que afecta tanto a echo $VAR como a env, Make y lo que se ponga a su paso.

Siendo dos aspectos afectados y dos puntos a combinar podría pensarse que falta una cuarta sintaxis: export VAR=val instr, sin el punto y coma. Sin embargo, esta sintaxis es una simple invocación a export, indicando que queremos exportar las variables VAR e instr.


Deja un comentario

Tu dirección de correo electrónico no será publicada. Los campos obligatorios están marcados con *