大容量のテキストデータファイルを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 val
MCWEを減らすために上記の単純化されたコードを試しました。
答え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
。