EOF 以降の Bash リードループは停止しません。

EOF 以降の Bash リードループは停止しません。

大容量のテキストデータファイルを1行ずつ読みたいです。サンプルコード:

lines=0
while IFS=$' \t\n'
do
    lines=$(($lines+1))
    read val
    echo "lines=$lines val=$val"
done < myfile

問題:ループはファイルの最後まで読みます!

$ wc -l myfile
41788 myfile

最初はすべてがうまくいき、データが印刷されていることがわかりますが、41788以降でもループは停止しません。カウンターは空白行で実行され続け、停止するにはCTRL-C'itを押す必要があります。

データファイルを確認しましたが、特別なものはありません。 size = 5088370バイト、フィールドはタブで区切られています(1)。

$ file myfile 
myfile: ISO-8859 text, with CRLF line terminators

ここで何が起こっているのかについての手がかりはありますか?私が逃したものは何ですか?

(1)このフィールドは実際に読み込まれましたが、read -a valMCWEを減らすために上記の単純化されたコードを試しました。

答え1

$' \t\n'IFS設定が成功する限り、ループが実行されることを意味します。次のようにする必要があります。

while IFS=$' \t\n' read -r val
do
    ((lines++))
    echo "lines=$lines val=$val"
done < myfile

のデフォルト値はこのように設定するIFS必要があるため、設定が重複する可能性があります。$' \t\n'また、私はread基本的に行全体を読むと思いますが、IFSをそのように設定しても、$' 'まだ行全体を読むことになると思います。

スペースで区切るには、次のスイッチをread使用します。-d

read -r -d' ' val
do
    ((lines++))
    echo "lines=$lines val=$val"
done < myfile

これは、文字列のスペースで区切られた各文字列を繰り返しますmyfile

関連情報