Linux

為什麼這個“while”循環不能辨識最後一行?

  • October 12, 2021

我們使用以下腳本:

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

為什麼會這樣?

您的輸入文本包含一個不完整的行作為其最後一行。最後一行沒有被換行符終止。

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

上面的循環將從呼叫的文件中讀取未修改的行¹(不去除空格或解釋反斜杠控制序列)file並將它們列印到標準輸出。

當讀取不完整read的行時,將失敗,但$line仍將包含數據。額外的-n測試將檢測到這一點,以便允許循環體輸出不完整的行。在那之後的迭代中,read將再次失敗並且$line將是一個空字元串,從而終止循環。


¹ 假設它們在 shell 中不包含 NUL 字元,zsh並且假設它們不包含不構成yashshell 中有效字元一部分的字節序列,如果輸入是有效文本,這兩種情況都不應該發生,儘管缺少最後一行的行分隔符已經使它成為無效文本。

引用自:https://unix.stackexchange.com/questions/482517