Чтение файла построчно в Perl - PullRequest
0 голосов
/ 29 апреля 2018

Я хочу прочитать файл одной строкой, но он читает только первую строку. Как читать все строки?

Мой код:

open(file_E, $file_E);

while ( <file_E> ) {
    /([^\n]*)/;
    print $line1;
}

close($file_E);

Ответы [ 2 ]

0 голосов
/ 30 апреля 2018

Еще одна альтернатива, обратите внимание, что $ _ будет включать в себя символ новой строки, поэтому вам нужно будет скомпоновать его, если вы не хотите, чтобы символ новой строки был в строке $:

open(file_E, $file_E);

while ( <file_E> ) {
    my $line = $_;
    print $line;
}

close($file_E);
0 голосов
/ 29 апреля 2018

Давайте начнем с просмотра вашего кода.

open(file_E, $file_E);

while ( <file_E> ) {
    /([^\n]*)/;
    print $line1;
}

close($file_E);

В первой строке вы открываете файл с именем в $file_E, используя дескриптор файла голого слова file_E. Это должно работать, пока файл успешно открывается. Также было бы лучше проверить успешность этой операции одним из двух способов: либо поместите use autodie; в начало вашего скрипта (но затем рискуйте применить его семантику в тех местах, где ваш код несовместим с этим уровнем обработки ошибок), или измените свой open, чтобы он выглядел так:

open(file_E, $file_E) or die "Failed to open $file_E: $!\n";

Теперь, если вам не удалось открыть файл, вы получите сообщение об ошибке, которое поможет отследить проблему.

Далее давайте посмотрим на цикл while, потому что именно здесь у вас есть проблема, которая вызывает ошибку, с которой вы столкнулись. В первой строке цикла while вы видите это:

while ( <file_E> ) {

Консультируясь с perldoc perlsyn, вы увидите, что эта строка специально для этого сделана:

while (defined($_ = <file_E>)) {

Таким образом, ваш код неявно присваивает каждой строке $_ на последовательных итерациях. Также, посоветовавшись с perldoc perlop, вы обнаружите, что когда вызывается оператор сопоставления (/.../ или m/.../) без явной привязки сопоставления с использованием =~, сопоставление сопоставляется с $_ , Тем не менее, пока все хорошо. Тем не менее, вы не делаете ничего полезного в матче. Оператор совпадения вернет логическую истину / ложь, если совпадение было успешным. А поскольку ваш шаблон содержит круглые скобки, он будет записывать что-то в переменную захвата $1. Но вы никогда не проверяете успех матча, и при этом вы никогда больше не ссылаетесь на $1.

В следующей строке вы делаете это: print $line1. Где, в вашем коде, $line1 присваивается значение? Потому что ему никогда не присваивается значение в том, что вы нам показали.

Я могу только догадываться, что ваше намерение состоит в том, чтобы перебрать строки файла, захватить строку, но без завершающего символа новой строки, а затем распечатать ее. Кажется, что вы хотите напечатать его без каких-либо новых строк, чтобы весь входной файл печатался как одна строка вывода.

open my $input_fh_e, '<', $file_E or die "Failed to open $file_E: $!\n";

while(my $line = <$input_fh_e>) {
    chomp $line;
    print $line;
}

close $input_fh_e or die "Failed to close $file_E: $!\n";

Не нужно ничего захватывать - если все, что делает захват, это просто захват всего до новой строки, вы можете просто удалить новую строку с помощью chomp для начала.

В моем примере я использовал лексический дескриптор файла (дескриптор файла с лексической областью, объявленный с my). Как правило, это лучший метод в современном Perl, так как он избегает использования голого слова, избегает возможных коллизий пространства имен и гарантирует, что дескриптор закроется, как только закроется лексическая область.

Я также использовал версию «10 arg» open, которая более безопасна, поскольку исключает возможность использования $file_E для открытия канала или выполнения каких-либо других гнусных или просто непреднамеренных манипуляций с оболочкой.

Я предлагаю также запустить ваш скрипт с use strict;, потому что если бы вы сделали это, вы получили бы сообщение об ошибке во время компиляции, сообщающее, что $line1 никогда не был объявлен. Также запустите ваш скрипт с use warnings, чтобы вы могли получить предупреждение при попытке напечатать $line1 перед присвоением ему значения.

Большинство проблем в вашем коде будут обсуждаться в perldoc perlintro, к которому вы можете обратиться из командной строки, просто набрав perldoc perlintro, предполагая, что у вас установлен Perl. Обычно на чтение perlintro уходит 20-40 минут. Если когда-либо существовал документ, который должен представлять собой обязательное чтение, прежде чем начать писать код на Perl, это чтение, вероятно, будет включать perlintro.

...