2016-02-20 5 views
0

Я совершенно не знаком с Perl, и мне была назначена какая-то задача ... Мне нужно прочитать файл с разделяемой вкладкой, а затем выполнить некоторые операции с данными в DB. Файл .tsv выглядит так:Создание многомерного массива при чтении файла - Perl

ID Имя Дата

155 Педро 1988-05-05

522 Mengano 2002-08-02

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

#Read file from path 
my @array; 
my $fh = path($filename)->openr_utf8; 
while (my $line = <$fh>) { 
    chomp $line; 
    # skip comments and blank lines and title line 
    next if $line =~ /^\#/ || $line =~ /^\s*$/ || $line =~ /^\+/ || $line =~ /ID/; 
    #split each line into array 
    my @aux_line = split(/\s+/, $line); 
    push @array, @{ $aux_line }; 
    } 

Очевидно, что последняя строка не работает ... как можно было бы сделать, чтобы создать массив массивы таким образом? Я немного потерялся со ссылками ... И кто-нибудь может подумать о том, как лучше хранить эти данные, которые мы читаем из файла? Спасибо!

+0

'push @array, \ @ $ aux_line;' –

+1

Я предполагаю, что этот вопрос ответил много раз. Используйте «Текст :: CSV» или «Текст :: CSV :: Slurp». Он может использовать первую строку в качестве имен полей, создает массив хэшей с именами полей в качестве ключа и почти готов для вставки в базу данных через «DBIx :: Class», если имена полей соответствуют именам столбцов БД. –

+0

Я думал сначала о решении с хешем, но разве это не сложнее управлять таким образом @HelmutWollmersdorfer? Поскольку у меня есть следующие условия, когда я читаю файл и подключаюсь к db: - Если в БД с данным идентификатором уже есть запись, эта запись обновляется информацией из файла, а Update_timestamp устанавливается на текущую временную метку системы. - Если новая запись обнаружена в файле, в базе данных создается новая запись с атрибутами из файла, а Update_timestamp - текущая временная метка системы. – ArtanisAce

ответ

1

Во-первых, use strict и use warnings. Это сразу предупредит вас о том, что ваш неправильный способ получить ссылку на массив пытается получить доступ к совершенно другой переменной (Perl позволяет переменной разных типов иметь одинаковые имена).

После этого просто измените последнюю строку на:

push @array, \@aux_line; 
+0

О, пытался попробовать что-то, но не это! Теперь я думаю, что получил смысл; передача ссылки не пропускает никакого значения, а только расположение памяти ... поэтому, когда вы используете «push», значения «@array_line» не попадают в «@array» правильно? Большое спасибо, Олег! – ArtanisAce

+0

В значительной степени так. На верхнем уровне у вас есть массив, заполненный ссылками на другие массивы. –

2

Вы также можете сделать это с map:

use Data::Dumper; 
my @stuff = map {[split]} <$fh>; 
print Dumper \@stuff; 

(с возможно Grep пропустить комментарии)

Но может удовлетворить ваш прецедент лучше использовать массив хешей:

my @stuff ; 
chomp(my @header = split ' ', <$fh>); 
while (<$fh>) { 
    my %this_row; 
    @this_row{@header} = split; 
    push (@stuff, \%this_row) ; 
} 
+0

В этом случае это решение на основе хэша почти наверняка превосходит его. – zdim

Смежные вопросы