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?

questionAnswers(3)

yourAnswerToTheQuestion