この「while」ループが最後の行を認識しないのはなぜですか?

この「while」ループが最後の行を認識しないのはなぜですか?

私たちは次のスクリプトを使います:

more test.sh
#!/bin/bash

while read -r line
do

echo $line

done < /tmp/file

ファイルは次のようになります。

kafka-broker,log.retention.hours,12
kafka-broker,default.replication.factor,2
fefolp-defaults,fefolp.history.fs.cleaner.interval,1d
fefolp-defaults,fefolp.history.fs.cleaner.maxAge,2d
fefolp-env,fefolp_daemon_memory,10000
blo-site,blo.nodemanager.localizer.cache.target-size-mb,10240
blo-site,blo.nodemanager.localizer.cache.cleanup.interval-ms,300000
ams-env,metrics_collector_heapsize,512
fefolp,hbase_master_heapsize,1408
fefolp,hbase_regionserver_heapsize,512
fefolp,hbase_master_xmn_size,192
core-site,blolp.proxyuser.ambari.hosts,*
core-site,Hadoop.proxyuser.root.groups,*
core-site,Hadoop.proxyuser.root.hosts,*
blo-site,blo.scheduler.minimum-allocation-mb,1024
blolp-env,fefolp_heapsize,4096

注 - 最後の行の後にスペースはありません!

ただし、スクリプトは次の行のみを印刷します(最後の行を除く)。

./test.sh
kafka-broker,log.retention.hours,12
kafka-broker,default.replication.factor,2
fefolp-defaults,fefolp.history.fs.cleaner.interval,1d
fefolp-defaults,fefolp.history.fs.cleaner.maxAge,2d
fefolp-env,fefolp_daemon_memory,10000
blo-site,blo.nodemanager.localizer.cache.target-size-mb,140
blo-site,blo.nodemanager.localizer.cache.cleanup.interval-ms,300
ams-env,metrics_collector_heapsize,51
fefolp,hbase_master_heapsize,1408
fefolp,hbase_regionserver_heapsize,542
fefolp,hbase_master_xmn_size,19
core-site,blolp.proxyuser.ambari.hosts,*
core-site,Hadoop.proxyuser.root.groups,*
core-site,Hadoop.proxyuser.root.hosts,*
blo-site,blo.scheduler.minimum-allocation-mb,1024

なぜこれが起こるのですか?

ベストアンサー1

入力テキストの最後の行に不完全な行があります。最後の行は改行文字で終わりません。

while IFS= read -r line || [ -n "$line" ]; do
    printf '%s\n' "$line"
done <file

上記のループは、呼び出されたファイルから未変更の行を読み取り(空白を削除したりバックスラッシュ制御シーケンスを解釈したりせず)、fileそれを標準出力として出力します。

いつ不完全read行の読み取りは失敗しますが、$lineまだデータが含まれています。追加の-nテストでは、これを検出してループ本体が不完全な行を出力できるようにします。その後の反復では、空の文字列でread再び失敗し、ループが終了します。$line


シェルにNUL文字が含まれておらず、シェルで有効な文字の一部をzsh形成しないバイトシーケンスが含まれていないと仮定すると、入力yashが有効なテキストであればどちらも発生しません。最後の行文字の行の区切りによって無効なテキストになりました。

おすすめ記事