проблема с кодом в perl - PullRequest
       1

проблема с кодом в perl

1 голос
/ 03 августа 2011

Моя проблема в том, что я не могу понять, почему мой код берет каждую строку из файла как один элемент массива, а не всю запись, начиная с AD до SS, как один элемент массива , Как вы можете видеть, мой файл начинается с AD и заканчивается на SS, что одинаково для всех следующих строк в данных. Но я хочу, чтобы массив содержал элементы, начинающиеся с AD до SS, которые будут содержать все строки между AD и SS, то есть BC ...., EG ...., FA ..... и т. Д., Не каждый линия как элемент. Я попробовал свой путь и получил тот же файл как таковой. Может ли кто-нибудь проверить мой код. Заранее спасибо.

н.э. uuu23

BC JJJ

EG iii

FA vvv

СС

н.э. ччх25

до н.э. ккк

EG ppp

FA aaa

СС

н.э. ttt26

до н.э. ххх

FA ррр

СС

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

 my $ifh;
 my $line = '';
 my @data;

 my $ifn  = "fac.txt";

 open ($ifh, "<$ifn") || die "can't open $ifn";
 my $a = "AD  "; 
 my $b = "SS ";
 my $_ = " ";
 while ($line = <$ifh>)
 {
 chomp 
 if ($line =~ m/$a/g); {
  $line = $_;

  push @data, $line;

 while ($line = <$ifh>) 
{
$line .= $_;

push @data, $line;

last if 
($line =~ m/$b/g);
}

}
push @data, $line; }


print @data;

Ответы [ 3 ]

2 голосов
/ 03 августа 2011

Если я правильно понимаю вашу проблему, дело в том, как вы читаете файл:

while ($line = <$ifh>)

по своей сути является построчным подходом. Он использует содержимое «переменной завершения строки» ($/), чтобы понять, где разбивать строки. Один простой способ изменить это поведение - это не определять $/:

 my $oldTerminator = $/;
 undef $/;
 ....... <your processing here>
 $/ = $oldTerminator;

Итак, ваш файл будет всего одной строкой, но я не уверен, что произойдет с вашим кодом.

Другой подход заключается в следующем (учитывая то, что я сказал о том, что вы читаете файл построчно): вместо выполнения

`push @data, $line;`

на каждой итерации цикла просто накапливайте строки, которые вы прочитали, в переменной

$line .= $_;

(как вы уже делаете), и выполните push только в конце, только один раз. На самом деле, этот второй подход будет более применим к вашему коду (вам нужно только удалить два имеющихся у вас оператора push и поместить один вне цикла).

1 голос
/ 03 августа 2011

Я считаю, что часть вашей проблемы здесь

chomp 
 if ($line =~ m/$a/g);

это должно быть

chomp;
if ($line =~ m/$a/g)

в противном случае оператор if всегда выполняется.Пожалуйста, обновите ваш вопрос, если это помогло вам продвинуться

0 голосов
/ 03 августа 2011

Вот способ завершить чтение записей в массив без удаленных строк:

Код:

use strict;
use warnings;
use autodie;

my @data;
my $record;
my $file = "fac.txt";
open my $fh, '<', $file;

while (<$fh>) {
    chomp;
    if (/^AD /) { # new record starts
        $record = $_;
        while (<$fh>) {
            chomp;
            $record .= $_;
            last if /^SS\s*/;
        }
        push @data, $record;
    } else { die "Data outside record: $_" }
}

use Data::Dumper;
print Dumper \@data;

Вывод:

$VAR1 = [
          'AD uuu23BC jjjEG iiiFA vvvSS',
          'AD hhh25BC kkkEG pppFA aaaSS',
          'AD ttt26BC xxxFA rrrSS'
        ];

Это еще одна версия, использующая разделитель входных записей $/:

use strict;
use warnings;
use autodie;

my $file = "fac.txt";
open my $fh, '<', $file;

my @data;
$/ = "\nSS";
while (<$fh>) {
    s/\n//g;
    push @data, $_;
}

use Data::Dumper;
print Dumper \@data;

Создает тот же вывод с этими данными.Его не волнуют начальные символы записи, только конец, который равен SS в начале строки.

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