TL; DR
Cada comando de una tubería se ejecuta dentro de una subshell, con su propio contexto y entorno de variables. Incluyendo los bucles si estos forman parte de la tubería.
La variable que desaparecía
El otro día trabajando con un script en bash
me volví un poco loco con una variable que modificaba dentro de un bucle while
y que luego parecía no guardar su valor una vez terminado el bucle. Como era un comportamiento que para nada esperaba me costó lo mio dar con el problema. No era un problema del bucle, si no de que éste formaba parte de una tubería (pipe):
var1=0
echo $VARIABLE1 |
while read task; do
# cuerpo del bucle
var1=2
# ...
done
echo "$var1"
> 0
Efectivamente, cada comando de una tubería se ejecuta dentro de una subshell, con su propio contexto y entorno de variables. Incluyendo los bucles si estos forman parte de la tubería.
En esta web se puede leer una descripción detallada de este comportamiento, qué sucede en las diferentes versiones de shell, así como diferentes maneras de sortearlo.
De las propuestas, la solución que decidí adoptar en mi caso fue el agrupamiento de comandos (Command grouping) así:
var1=0
echo $VARIABLE1 |
{
while read task; do
# cuerpo del bucle
var1=2
# ...
done
echo "$var1"
}
> 2
Que, como explican en la página, no altera para nada el tema de la subshell, pero como en este caso no necesitaba reutilizar nada de lo que allí había en el resto del código, resulta una solución suficiente y rápida de aplicar.
De paso, he descubierto esta página que parece que va a ser una referencia útil a la que volver de vez en cuando.