Qual é a maneira mais defensiva de percorrer as linhas em um arquivo com Perl?
Normalmente, faço um loop pelas linhas de um arquivo usando o seguinte código:
open my $fh, '<', $file or die "Could not open file $file for reading: $!\n";
while ( my $line = <$fh> ) {
...
}
Contudo,em responder a outra pergunta, Evan Carroll editei minha resposta, alterando minhawhile
declaração para:
while ( defined( my $line = <$fh> ) ) {
...
}
A lógica dele era que, se você tem uma linha que é0
(teria que ser a última linha, caso contrário, teria um retorno de carro), então seuwhile
sairia prematuramente se você usasse minha declaração ($line
seria definido como"0"
e o valor de retorno da atribuição também seria"0"
que é avaliado como falso). Se você verificar a definição, não encontrará esse problema. Faz todo o sentido.
Então eu tentei. Eu criei um arquivo de texto cuja última linha é0
sem retorno de carro. Passei-o pelo meu loop e o loop não saiu prematuramente.
Então pensei: "Ah, talvez o valor não seja realmente0
, talvez haja algo mais que estrague tudo! "Então eu useiDump()
deDevel::Peek
e é isso que me deu:
SV = PV(0x635088) at 0x92f0e8
REFCNT = 1
FLAGS = (PADMY,POK,pPOK)
PV = 0X962600 "0"\0
CUR = 1
LEN = 80
Isso parece me dizer que o valor é realmente a string"0"
, pois eu obtenho um resultado semelhante se eu ligarDump()
em um escalar que eu defini explicitamente para"0"
(a única diferença está no campo LEN - do arquivo LEN é 80, enquanto no LEN escalar é 8).
Então, qual é o problema? Por que meuwhile()
loop sair prematuramente se eu passar uma linha que é apenas"0"
sem retorno de carro? O loop de Evan é realmente mais defensivo ou o Perl faz algo louco internamente que significa que você não precisa se preocupar com essas coisas ewhile()
na verdade, só sai quando você bateeof
?