パイプを用いたwhile文の落とし穴

いやー、まいった。超落とし穴にはまった。


最近仕事で触る機会がぐっと増えたシェル(主にbash)なのだが、いろいろとうまくいってない。
今日はwhileを使った処理でがっつり落とし穴にはまった。たとえば以下のようなC言語のプログラムがある

int idx = 0
while(idx < 3) {
    idx += 1
}
printf("%d", idx)


最後のprintf文で出力される値は当然「3」。同じような感覚でシェルでもこんな書き方をした

IDX=0
cat ${INPUT_FILE} | while read LINE
do
    IDX=`expr $IDX + 1`
done
echo $IDX

ちょっとC言語の例とは違っているが、やっているのはINPUT_FILEの行数を数えるだけの処理である。
しかし、最後に出力されるIDXの値は0となる。これはパイプを使用するとそのあとの処理が別シェルで実行されてしまうからである。
つまり、最初に定義されているIDXとwhileの中にあるIDXは同じ名前の赤の他人ということである。


今日はこれにつまずいた...なぜもっと早くググらなかったのか。課題は増える一方だ。
まさか「読み込んでいるファイルが最初に来るし、この書き方の方がわかりやすい!」と思って書いた方法でこんなことになるとは。
ちなみに下記のように書けば問題なく動きます。

IDX=0
while read LINE
do
    IDX=`expr $IDX + 1`
done < ${INPUT_FILE}
echo $IDX