Como ler linha por linha um arquivo somente CR com Perl?
-
26-09-2019 - |
Pergunta
Estou tentando ler um arquivo que possui apenas CR como delimitador de linha. Estou usando o Mac OS X e o Perl v.5.8.8. Esse script deve ser executado em todas as plataformas, para todo tipo de delimitador de linha (CR, LF, CRLF).
Meu código atual é o seguinte:
open(FILE, "test.txt");
while($record = <FILE>){
print $record;
}
close(TEST);
Atualmente, imprima apenas a última linha (ou o pior). O que está acontecendo? Obviamente, eu gostaria de não converter o arquivo. É possível?
Solução
Você pode definir o delimitador usando a variável especial $/
:
local $/ = "\r" # CR, use "\r\n" for CRLF or "\n" for LF
my $line = <FILE>;
Ver PerlDoc Perlvar para mais informações.
Outra solução que funciona com todos os tipos de linebreaks seria ingerir o arquivo inteiro de uma só vez e depois dividi -lo em linhas usando um regex:
local $/ = undef;
my $content = <FILE>;
my @lines = split /\r\n|\n|\r/, $content;
Você não deve fazer isso com arquivos muito grandes, pois o arquivo é lido completamente na memória. Observe que definir $/ para o valor indefinido desativa o delimitador de linha, o que significa que tudo é lido até o final do arquivo.
Outras dicas
Eu resolvi um problema mais geral que poderia ser útil aqui:
Como analisar grandes arquivos linha por linha com qualquer delimitador de linha (CR/CRLF/LF), mas desconhecido antes.
Arquivo 'Big' significa que não é bom ler o arquivo inteiro em uma variável. Aqui a função 'Detectendofline' obtém o nome do arquivo e retorna ' r' ou ' n', o que for usado para o final da linha (ele pesquisou ' r' ou ' n' símbolo char-by-char a partir do final do arquivo).
my $file = "test.txt";
local $/ = detectEndOfLine($file);
open(IN, $file) or die "Can't open file \"$file\" for reading: $!\n";
while(<IN>) {
s/\r\n|\n|\r$//;
print "$_\n";
}
sub detectEndOfLine {
my $file = $_[0];
my $size = -s $file;
print "\"$size\"\n";
open(IN, $file) or die "Can't open file \"$file\" for reading: $!\n";
for(my $i = $size; $i >= 0; --$i) {
seek(IN, $i, 0);
$_ = <IN>;
my $sym = substr($_, 0, 1);
return $sym if( $sym eq "\n" or $sym eq "\r" );
}
return undef;
}