Problema con variables en un bucle que está en una tubería

bash
tubería
Autor/a

David Mateos

Fecha de publicación

24 de agosto de 2017

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.

Fuente:

BashFAQ