Как читать построчно CR-файл только с Perl? - PullRequest
3 голосов
/ 11 июня 2010

Я пытаюсь прочитать файл, в котором в качестве разделителя строк используется только CR. Я использую Mac OS X и Perl v.5.8.8. Этот сценарий должен выполняться на каждой платформе для каждого типа разделителя строк (CR, LF, CRLF).

Мой текущий код следующий:

open(FILE, "test.txt");

while($record = <FILE>){
    print $record;
}

close(TEST);

В настоящее время печатается только последняя строка (или худшая). Что здесь происходит? Очевидно, я не хотел бы конвертировать файл. Возможно ли это?

Ответы [ 2 ]

20 голосов
/ 11 июня 2010

Вы можете установить разделитель, используя специальную переменную $/:

local $/ = "\r" # CR, use "\r\n" for CRLF or "\n" for LF
my $line = <FILE>;

См. perldoc perlvar для получения дополнительной информации.

Другим решением, которое работает со всеми видами разрывов строк, было бы разбить весь файл сразу, а затем разбить его на строки с помощью регулярного выражения:

local $/ = undef;
my $content = <FILE>;
my @lines = split /\r\n|\n|\r/, $content;

Вы не должны делать это с очень большими файлами, так как файл полностью считывается в память. Обратите внимание, что установка $ / неопределенное значение отключает разделитель строки, что означает, что все читается до конца файла.

1 голос
/ 04 июня 2013

Я решил более общую проблему, которая может быть полезна здесь:

Как анализировать большой файл построчно с любым разделителем строк (CR / CRLF / LF), но заранее неизвестным.

«Большой» файл означает, что нельзя читать весь файл в одну переменную.Здесь функция 'detectEndOfLine' получает имя файла и возвращает либо '\ r', либо '\ n', независимо от того, что используется для окончания строки (она искала символ '\ r' или '\ n' char-by-char, начиная сконец файла).

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;
}
...