35 votos

bash: variable pierde su valor al final del bucle while read

Tengo un problema en una de mis secuencias de comandos de shell. Pregunté a un par de colegas, pero todos ellos sólo agitar sus cabezas (después de algunos roces), así que he venido aquí para una respuesta.

De acuerdo, a mi entender, la siguiente secuencia de comandos de shell debe imprimir "Número es de 5" como la última línea. Excepción no. Se imprime "Count es 0". Si el "mientras que la lectura" es reemplazado por cualquier otro tipo de bucle, funciona muy bien. Aquí está la secuencia de comandos:

echo "1">de entrada.datos
echo "2">>de entrada.datos
echo "3">>de entrada.datos
echo "4">>de entrada.datos
echo "5">>de entrada.datos

CNT=0 

gato de entrada.datos | while read ;
¿
 vamos a CNT++;
 echo "Contando a $CNT"
hecho 
echo "la cuenta es de $CNT"

¿Por qué sucede esto y cómo se puede prevenir? He intentado esto en Debian Lenny, Squeeze, mismo resultado (es decir, bash 3.2.39 y bash 4.1.5. Estoy totalmente de admitir a no ser un script de shell asistente, de manera que los punteros se agradece.

30voto

30voto

coredump Puntos 9198

Esta es una especie de 'común' error. Tubos de crear SubShells, por lo que el while read está ejecutando en una consola diferente de la secuencia de comandos, lo que hace que su CNT variable no cambia nunca (sólo el uno en el interior de la tubería subshell).

Grupo de la última echo con el subshell while solucionarlo (hay muchas otras manera de solucionarlo, este es uno. Iain y Ignacio respuestas de los demás.)

CNT=0

 cat input.data | ( while read 
do
  let CNT++;
  echo "Counting to $CNT"
done 
echo "Count is $CNT" )

Larga explicación:

  1. Se declara CNT en su secuencia de comandos a ser el valor 0;
  2. Una SubShell se inicia en el | a while read;
  3. Su $CNT variable se exporta a la SubShell con el valor 0;
  4. El SubShell cuenta y aumentar el CNT del valor a 5;
  5. SubShell extremos, las variables y los valores son destruidos (que no regrese al proceso de llamada/script).
  6. Usted echo original CNT valor de 0.

10voto

katit Puntos 130

Esto funciona

CNT=0 

while read ;
do
  let CNT++;
  echo "Counting to $CNT"
done <input.data
echo "Count is $CNT"

EnMiMaquinaFunciona.com

EnMiMaquinaFunciona es una comunidad de administradores de sistemas en la que puedes resolver tus problemas y dudas.
Puedes consultar las preguntas de otros sysadmin, hacer tus propias preguntas o resolver las de los demás.

Powered by: