Variable manipulation from within a Bash subshell

Consider a shell script that counts the number of lines in a file. There are a number of ways to do this and I initially chose the following method:

NUMLINES=0
cat /tmp/file.txt | while read LINE;
do
NUMLINES=`expr $NUMLINES + 1`
done
echo "Number of lines was $NUMLINES"

However, using this approach the value of NUMLINES was always zero after the while loop has ended, even though when I printed out its value inside the while loop it appeared to be incrementing just fine.

The problem turned out to be the use of the pipe at the beginning of the the while loop. This causes a new sub-shell to be created, which in turn creates a new local version of the NUMLINES. Thus, the original copy of the NUMLINES variable (outside the while loop) is never actually changed. Here is one solution to this that eliminates the use of the pipe (i.e. replace the piping of the file in the while with a redirection from the file at the end of the while statement):

NUMLINES=0
while read LINE;
do
NUMLINES=`expr $NUMLINES + 1`
done < /tmp/file.txt
echo "Number of lines was $NUMLINES"

This worked for me!