Por que esse loop 'while' não reconhece a última linha?

2

Nós usamos o seguinte script:

more test.sh
#!/bin/bash

while read -r line
do

echo $line

done < /tmp/file

Este é o arquivo:

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

Observação - depois da última linha - não há espaço!

Mas o script imprime apenas essas linhas (exceto a última linha):

./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

Por que isso acontece?

    
por yael 18.11.2018 / 12:46

1 resposta

6

Seu texto de entrada contém uma linha incompleta como sua última linha. A última linha não é terminada por uma nova linha.

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

O loop acima irá ler linhas não modificadas (sem remover espaços em branco ou interpretar sequências de controle com barra invertida) do arquivo chamado file e imprimi-las na saída padrão.

Quando uma linha incompleta é lida, read falhará, mas $line ainda conterá dados. O teste -n extra detectará isso para que o corpo do loop tenha permissão para produzir a linha incompleta. Na iteração depois disso, read falhará novamente e $line será uma string vazia, finalizando o loop.

    
por 18.11.2018 / 13:17