Linux
為什麼這個“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
為什麼會這樣?
您的輸入文本包含一個不完整的行作為其最後一行。最後一行沒有被換行符終止。
while IFS= read -r line || [ -n "$line" ]; do printf '%s\n' "$line" done <file
上面的循環將從呼叫的文件中讀取未修改的行¹(不去除空格或解釋反斜杠控制序列)
file
並將它們列印到標準輸出。當讀取不完整
read
的行時,將失敗,但$line
仍將包含數據。額外的-n
測試將檢測到這一點,以便允許循環體輸出不完整的行。在那之後的迭代中,read
將再次失敗並且$line
將是一個空字元串,從而終止循環。¹ 假設它們在 shell 中不包含 NUL 字元,
zsh
並且假設它們不包含不構成yash
shell 中有效字元一部分的字節序列,如果輸入是有效文本,這兩種情況都不應該發生,儘管缺少最後一行的行分隔符已經使它成為無效文本。