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?

Foi útil?

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;
}
Licenciado em: CC-BY-SA com atribuição
Não afiliado a StackOverflow
scroll top