как поместить файл в массив и сохранить его в perl - PullRequest
1 голос
/ 10 июля 2011

Привет всем, я новичок в Perl, и у меня возникают некоторые проблемы, так как я хочу поместить свои строки, начиная с AA, в массив, и сохранить его. В текстовом файле содержится около 2000-3000 строк, начинающихся с одинаковых инициалов, т. Е. АА / я делаю это таким образом, пожалуйста, исправьте меня, если я ошибаюсь.

Входной файл

AA  c0001
BB  afsfjgfjgjgjflffbg
CC  table
DD  hhhfsegsksgk
EB  jksgksjs
\
AA  e0002
BB  rejwkghewhgsejkhrj
CC  chair
DD  egrhjrhojohkhkhrkfs
VB  rkgjehkrkhkh;r
\

Исходный код

$flag = 0
while ($line = <ifh>)
{

    if ( $line = m//\/g)
    {
        $flag = 1;
    }
    while ( $flag != 0)
    {
        for ($i = 0; $i <= 10000; $i++)
        { # Missing brace added by editor
            $array[$i] = $line;
        } # Missing brace added by editor
    }
}  # Missing close brace added by editor; position guessed!
print $ofh, $line;

close $ofh;

Ответы [ 4 ]

8 голосов
/ 10 июля 2011

Добро пожаловать в StackOverflow.

Есть несколько проблем с вашим кодом.Во-первых, пожалуйста, отправьте скомпилированный Perl;Мне пришлось добавить три фигурных скобки, чтобы дать ему самый отдаленный шанс компиляции, и я должен был угадать, куда делся один из них (и есть умеренный шанс, что он должен быть на другой стороне оператора print, откуда я его положил).

Далее эксперты имеют:

use warnings;
use strict;

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

После того, как они будут созданы, вы должны объявить свои переменные по мере их использования.

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

Является лиEB против VB в данных значимых?Трудно догадаться.

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

У вас есть строка while ($line = <ifh>).Это не недействительно в Perl, если вы открыли файл старомодным способом, но это не тот способ, которым вы должны учиться.Вы не показываете, как открывается дескриптор выходного файла, но вы используете современные обозначения при попытке печати на него.Однако есть и ошибка:

print $ofh, $line;  # Print two values to standard output
print $ofh  $line;  # Print one value  to $ofh

Вам нужно внимательно посмотреть на свой код и подумать о логике циклов.Я уверен, что у вас есть не то, что вам нужно.Однако я не уверен, что вам нужно.

Более простое решение

Из комментариев:

Я хочу пометить каждую запись, начиная сОт AA до \ как от записи 0 до записи n, и вы хотите сохранить ее в новом файле со всеми номерами записей.

Тогда вам, вероятно, просто нужно:

#!/usr/bin/env perl
use strict;
use warnings;
my $recnum = 0;
while (<>)
{
    chomp;
    if (m/^\\$/)
    {
        print "$_\n";
        $recnum++;
    }
    else
    {
        print "$recnum $_\n";
    }
}

Он считывает файлы, указанные в командной строке (или стандартный ввод, если таковых нет), и записывает помеченный вывод в стандартный вывод.Он префикс каждой строки, кроме строк маркера «конец записи», с номером записи и пробелом.Выберите выходной формат и обработку файлов в соответствии с вашими потребностями.Вы можете утверждать, что chomp контрпродуктивен;Вы, конечно, можете закодировать программу без нее.

Слишком сложное решение

Разработано при отсутствии четкого направления от спрашивающего .

Вот одинвозможный способ чтения данных, но он использует умеренно продвинутый Perl (ссылки на хеш и т. д.).Модуль Data::Dumper также полезен для распечатки структур данных Perl (см. perldoc Data::Dumper).

#!/usr/bin/env perl

use strict;
use warnings;
use Data::Dumper;

my @data;
my $hashref = { };
my $nrecs = 0;

while (<>)
{
    chomp;
    if (m/^\\$/)
    {
        # End of group - save to data array and start new hash
        $data[$nrecs++] = $hashref;
        $hashref = { };
    }
    else
    {
        m/^([A-Z]+)\s+(.*)$/;
        $hashref->{$1} = $2;
    }
}

foreach my $i (0..$nrecs-1)
{
    print "Record $i:\n";
    foreach my $key (sort keys $data[$i])
    {
        print "  $key = $data[$i]->{$key}\n";
    }
}
print Data::Dumper->Dump([ \@data ], [ '@data' ]);

Пример вывода для примера ввода:

Record 0:
  AA = c0001
  BB = afsfjgfjgjgjflffbg
  CC = table
  DD = hhhfsegsksgk
  EB = jksgksjs
Record 1:
  AA = e0002
  BB = rejwkghewhgsejkhrj
  CC = chair
  DD = egrhjrhojohkhkhrkfs
  VB = rkgjehkrkhkh;r
$@data = [
           {
             'EB' => 'jksgksjs',
             'CC' => 'table',
             'AA' => 'c0001',
             'BB' => 'afsfjgfjgjgjflffbg',
             'DD' => 'hhhfsegsksgk'
           },
           {
             'CC' => 'chair',
             'AA' => 'e0002',
             'VB' => 'rkgjehkrkhkh;r',
             'BB' => 'rejwkghewhgsejkhrj',
             'DD' => 'egrhjrhojohkhkhrkfs'
           }
         ];

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

2 голосов
/ 10 июля 2011

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

Чтобы узнать о специальных переменных Perl, связанных с обработчиками файлов, прочитайте perlvar

#!perl

use strict;
use warnings;

my $content;

{
    open my $fh, '<', 'test.txt';
    local $/; # slurp mode
    $content = <$fh>;
    close $fh;
}

my @blocks = split /\\/, $content;

Убедитесь, что локализованы изменения специальных переменных Perl, чтобы они не мешали различным частям вашей программы.

Если вы хотите сохранить разделитель, вы можете установить $/ в \ напрямую и пропустить разделение.

#!perl

use strict;
use warnings;

my @blocks;

{
    open my $fh, '<', 'test.txt';
    local $/ = '\\'; # seperate at \
    @blocks = <$fh>;
    close $fh;
}
2 голосов
/ 10 июля 2011

Это не может быть правдой. Я вижу две основные проблемы с вашим циклом while.

После ввода следующего цикла

while ( $flag != 0)
{
  ...
}

вы никогда не выйдете из строя, потому что вы не сбрасываете флаг, когда находите разрывную строку. При необходимости вам придется проанализировать ввод и выйти из цикла.

И во-вторых, вы никогда не читаете никаких входных данных в этом цикле и, таким образом, обрабатываете один и тот же $line снова и снова.

Вы не должны помещать цикл в ваш код, но вместо этого вы можете использовать следующий шаблон (псевдокод)

if flag != 0
    append item to array
else
    save array to file
    start with new array
end
1 голос
/ 10 июля 2011

Вот способ прочитать ваши данные в массив.Как я сказал в комментарии, «сохранять» эти данные в файл бессмысленно, если вы не измените их.Потому что, если бы я напечатал приведенный ниже массив @data в файл, он бы выглядел точно как входной файл.

Итак, вы должны сказать нам, что именно вы хотитеВыполните, прежде чем мы сможем дать вам ответ о том, как это сделать.

Этот скрипт следует следующим точным правилам:

  • Найдите строку, начинающуюся с "AA", и сохранитеэто в $line
  • Объединить каждую новую строку из файла в $line
  • Когда вы найдете строку, которая начинается с обратной косой черты \, остановите объединение строк и сохраните $lineв @data.
  • Затем найдите следующую строку, которая начинается с «AA», и начните цикл заново.

Эти подходящие регулярные выражения довольно свободны, так как они будут соответствовать AAARGH и \bonkers.Если они вам нужны строже, вы можете попробовать /^\\$/ и /^AA$/, но тогда вам нужно остерегаться пробелов в начале и конце строки.Так что возможно /^\s*\\\s*$/ и /^\s*AA\s*$/ вместо.

Код:

use warnings;
use strict;

my $line="";
my @data;

while (<DATA>) {
    if (/^AA/) {
        $line = $_;
        while (<DATA>) {
            $line .= $_;
            last if /^\\/;
        }
    }
    push @data, $line;
}

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

__DATA__
AA  c0001
BB  afsfjgfjgjgjflffbg
CC  table
DD  hhhfsegsksgk
EB  jksgksjs
\
AA  e0002
BB  rejwkghewhgsejkhrj
CC  chair
DD  egrhjrhojohkhkhrkfs
VB  rkgjehkrkhkh;r
\
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...