Обработка файлов Perl - PullRequest
       4

Обработка файлов Perl

1 голос
/ 11 августа 2010

Ниже приведен скрипт на Perl, который я написал сегодня.Это читает содержимое из одного файла и записывает в другой файл.Это работает, но не полностью.

#---------------------------------------------------------------------------
#!/usr/bin/perl

open IFILE, "text3.txt" or die "File not found";
open OFILE, ">text4.txt" or die "File not found";

my $lineno = 0;

while(<IFILE>)
{
 @var=<IFILE>;
 $lineno++;
 print OFILE "@var";
}

close(<IFILE>);
close(<OFILE>);
#---------------------------------------------------------------------------

Проблема в том, что он читает и записывает содержимое, но не все.text3.txt имеет четыре строки.Вышеуказанный скрипт читает только со второй строки и пишет в text4.txt.Итак, наконец я получаю только три строки (line.no 2 - line.no 4) text3.txt.

Что не так с вышеуказанной программой.Я не имею ни малейшего представления о том, как проверить ход выполнения сценариев Perl.Пожалуйста, помогите мне.

Я совершенно новичок в программировании.Я верю, что изучение всего этого поможет мне изменить карьеру.

Заранее спасибо,

Виджай

Ответы [ 5 ]

3 голосов
/ 11 августа 2010

<IFILE> читает одну строку из IFILE (только одну, потому что она в скалярном контексте). Таким образом, while(<IFILE>) читает первую строку, затем <IFILE> в контексте списка в блоке while читает остальные. Что вы хотите сделать, это:

# To read each line one by one:
while(!eof(IFILE)) { # check if end of file is reached instead of reading a line
  my $line = <IFILE>; # scalar context, reads only one line
  print OFILE $line;
}

# Or to read the whole file at once:
my @content = <IFILE>; # list context, read whole file
print OFILE @content;
1 голос
/ 11 августа 2010

Вот как бы я написал код в вашем вопросе.

#!/usr/bin/perl
use warnings;
use strict;
use autodie;

# don't need to use "or die ..." when using the autodie module
open my $input,  '<', 'text3.txt';
open my $output, '>', 'text4.txt';

while(<$input>){
  my $lineno = $.;
  print {$output} $_;
}
# both files get closed automatically when they go out of scope
# so no need to close them explicitly

Я бы рекомендовал всегда , помещая use strict и use warnings в начало всех файлов Perl. По крайней мере, пока вы не знаете точно , почему это рекомендуется.

Я использовал autodie, поэтому мне не пришлось проверять возвращаемое значение open вручную. (autodie был добавлен в Core в версии 5.10.1)

Я использовал форму трех аргументов open, потому что она более устойчива.

Важно отметить, что while (<$input>){ ... } преобразуется компилятором в while (defined($_ = <$input>)){ ... }. Это означает, что текущая строка находится в переменной $_.

Я также использовал специальную переменную $., чтобы получить текущий номер строки, вместо того, чтобы пытаться самостоятельно отслеживать номер.

1 голос
/ 11 августа 2010

Проблема в том, что эта строка ...

while(<IFILE>)

... читает одну строку из text3.txt, а затем эту строку ...

@var=<IFILE>;

... читает ВСЕ оставшиеся строки из text3.txt.

Вы можете сделать это в любом случае, выполнив цикл с while или все сразу с @var=<IFILE>, но попытка сделать то и другое не сработает.

0 голосов
/ 11 августа 2010

Есть пара вопросов, о которых вы можете подумать, если вы строго копируете файл, вы можете использовать модуль File :: Copy.

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

Это зависит от того, что вы делаете под ним.Также, если у вас огромный двоичный файл, каждая строка в цикле while может оказаться огромной, поэтому, если память действительно является проблемой, вы можете использовать более низкоуровневое потоковое чтение, больше информации о вводе / выводе: http://oreilly.com/catalog/cookbook/chapter/ch08.html

Я бы предложил использовать метод очистки PBP следующим образом:

#!/usr/bin/perl

use strict;
use warnings;
use English qw(-no_match_vars);

my $in_file  = 'text3.txt';
my $out_file = 'text4.txt';

open my $in_fh,  '<', $in_file  or die "Unable to open '$in_file': $OS_ERROR";
open my $out_fh, '>', $out_file or die "Unable to open '$out_file': $OS_ERROR";

while (<$in_fh>) {
    # $_ is automatically populated with the current line
    print { $out_fh } $_ or die "Unable to write to '$out_file': $OS_ERROR";
}

close $in_fh  or die "Unable to close '$in_file': $OS_ERROR";
close $out_fh or die "Unable to close '$out_file': $OS_ERROR";

ИЛИ просто распечатать весь файл напрямую:

#!/usr/bin/perl

use strict;
use warnings;
use English qw(-no_match_vars);

my $in_file  = 'text3.txt';
my $out_file = 'text4.txt';

open my $in_fh,  '<', $in_file  or die "Unable to open '$in_file': $OS_ERROR";
open my $out_fh, '>', $out_file or die "Unable to open '$out_file': $OS_ERROR";

local $INPUT_RECORD_SEPARATOR; # Slurp mode, read in all content at once, see: perldoc perlvar

print { $out_fh } <$in_fh> or die "Unable to write to '$out_file': $OS_ERROR";;

close $in_fh  or die "Unable to close '$in_file': $OS_ERROR";
close $out_fh or die "Unable to close '$out_file': $OS_ERROR";

Кроме того, если вы просто хотите быстро применить регулярное выражение или аналог к ​​файлу, вы можете посмотреть ключ -i команды perl: perldoc perlrun

perl -p -i.bak -e 's/foo/bar/g' text3.txt; # replace all foo with bar in text3.txt and save original in text3.txt.bak
0 голосов
/ 11 августа 2010

Когда вы закрываете файлы, используйте

close(IFILE);
close(OFILE);

Когда вы окружаете файловый дескриптор угловыми скобками, такими как <IFILE>, Perl интерпретирует это как «прочитать строку текста из файла внутри угловых скобок». Вместо того, чтобы читать из файла, вы хотите закрыть сам файл.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...