O loop de leitura do Bash não para após o EOF

5

Eu quero ler um arquivo de dados de texto grande, linha por linha. Exemplo de código:

lines=0
while IFS=$' \t\n'
do
    lines=$(($lines+1))
    read val
    echo "lines=$lines val=$val"
done < myfile

Problema: o loop lê após o final do arquivo!

$ wc -l myfile
41788 myfile

Ele vai bem no começo, eu posso ver os dados impressos, mas o loop não pára após 41788. O contador continua correndo com linhas vazias e eu tenho que CTRL-C'it parar.

Verifiquei o arquivo de dados, nada de especial. size = 5088370 bytes, os campos são separados por tabulações (1).

$ file myfile 
myfile: ISO-8859 text, with CRLF line terminators

Alguma pista do que está acontecendo aqui? Eu senti falta de alguma coisa?

(1) Os campos são realmente lidos com read -a val , mas eu tentei o código simplificado acima para reduzir meu MCWE.

    
por kebs 23.12.2017 / 16:21

1 resposta

11

Você está dizendo que enquanto o IFS foi definido como $' \t\n' , seu loop será executado. Deve ser algo assim:

while IFS=$' \t\n' read -r val
do
    ((lines++))
    echo "lines=$lines val=$val"
done < myfile

O valor padrão de IFS deve ser $' \t\n' , portanto, defini-lo como redundante. Eu também acredito que read por padrão lerá linhas inteiras, e eu acho que mesmo configurar o IFS para $' ' ainda fará com que ele leia toda a linha.

Se você quiser que read delimite por espaços, você pode usar a opção -d desta forma:

read -r -d' ' val
do
    ((lines++))
    echo "lines=$lines val=$val"
done < myfile

Isso irá percorrer todas as strings delimitadas por espaços em myfile .

    
por 23.12.2017 / 16:23