¿Por qué mi contador Bash se restablece después del ciclo while?

Tengo un script Bash en el que quiero contar cuántas cosas se hicieron al pasar por un archivo. El recuento parece funcionar dentro del ciclo, pero después de eso la variable parece restablecerse.

nKeys=0 cat afile | while read -r line do #...do stuff let nKeys=nKeys+1 # this will print 1,2,..., etc as expected echo Done entry $nKeys done # PROBLEM: this always prints "... 0 keys" echo Finished writing $destFile, $nKeys keys 

El resultado de lo anterior es algo solo, las líneas de:

 Entrada hecha 1
 Entrada hecha 2
 Terminó de escribir / blah, 0 teclas

El resultado que quiero es:

 Entrada hecha 1
 Entrada hecha 2
 Terminé de escribir / bla, 2 llaves

No estoy muy seguro de por qué nKeys está 0 después del ciclo 🙁 Supongo que es algo básico, pero maldito si puedo detectarlo a pesar de mirar http://tldp.org/HOWTO/Bash-Prog-Intro-HOWTO-7.html y otros recursos.

Con los dedos cruzados, alguien más puede mirarlo y decir “¡bien, duh! ¡Tienes que …”!

En Bash 4.2 recién publicado, puede hacer esto para evitar la creación de una subcapa:

 shopt -s lastpipe 

Además, como probablemente verás en el enlace que proporcionó Ignacio, tienes un uso inútil del cat .

 while read -r line do ... done < afile 

Como se menciona en la respuesta aceptada, esto sucede porque las tuberías generan subprocesos separados. Para evitar esto, la command grouping ha sido la mejor opción para mí. Es decir, hacer todo después de la tubería en una subcapa.

 nKeys=0 cat afile | { while read -r line do #...do stuff let nKeys=nKeys+1 # this will print 1,2,..., etc as expected echo Done entry $nKeys done # PROBLEM: this always prints "... 0 keys" echo Finished writing $destFile, $nKeys keys } 

Ahora informará el valor de $nKeys “correctamente” (es decir, lo que desea).

Llegué al resultado deseado de la siguiente manera sin usar tuberías o aquí documentos

 #!/bin/sh counter=0 string="apple orange mango egg indian" str_len=${#string} while [ $str_len -ne 0 ] do c=${string:0:1} if [[ "$c" = [aeiou] ]] then echo -n "vowel : " echo "- $c" counter=$(( $counter + 1 )) fi string=${string:1} str_len=${#string} done printf "The number of vowels in the given string are : %s "$counter echo