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

Se tarda en leer ~1 minuto

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

Comentarios


Testing I

> Nadie quiere hablar sobre *testing*. *Testing* es el patito feo del desarrollo de software. El problema es que todos/as sabemos que el ...… Seguir leyendo

Importar funciones de otro paquete en R

Publicado el 06 de agosto de 2021

Understanding Software I

Publicado el 20 de septiembre de 2020