シェルスクリプトでwhile文で使用した変数がループ外で反映されない場合

下記のようなシェルスクリプトでwhileループ内読み込んだファイルの内容を表示して、行数をカウントしています。
while内では、変数が表示されますがwhileループの外だと変数は「0」と表示されます

#!/bin/bash

FILE=/var/tmp/file.txt
CNT=0

cat $FILE | while read line; do
    CNT=`expr ${CNT} + 1`
    echo $line
done

echo "CNT:$CNT"

出力結果

$ cat /var/tmp/file.txt
apricot
melon
peach
apple
grape

$ sh test.sh 
apricot
melon
peach
apple
grape
CNT:0

上記のスクリプトでは、ループ内で実行される変数が「0」となっています。これは、whileループがサブシェル内で実行されるためです。
whileループの処理を実行する際に、パイプ演算子( | )を使用してパイプで繋がれたコマンドに対して入力しているので、whileループはサブシェルで実行されているので、ループ内で宣言された変数や変更が、ループ外のスコープには影響を与えないので「0」となります。

whileループ内の変数をループ外で使用したい場合は、リダイレクト(<) を使用してファイルを読み込めば、ループはサブシェルではなく、実行中のシェル内で直接実行されます。

【修正後のシェルスクリプト】

$ vi test.sh
#!/bin/bash

FILE=/var/tmp/file.txt
CNT=0

while read -r line; do
    CNT=`expr ${CNT} + 1`
    echo $line
done < "$FILE"

echo "CNT:$CNT"

# 実行結果
$ sh test.sh
apricot
melon
peach
apple
grape
CNT:5

 

スポンサーリンク

0
0