Чтение разделов из файла на Perl
Вопрос
Я пытаюсь прочитать значения из входного файла на Perl.Входной файл выглядит следующим образом:
1-sampledata1 This is a sample test
and data for this continues
2-sampledata2 This is sample test 2
Data for this also is on second line
Я хочу прочитать приведенные выше данные, чтобы данные для 1-sampledata1
переходит в @array1
и данные для 2-sampledata2
входит @array2
и так далее.У меня будет около 50 таких разделов, как этот.Нравится 50-sampledata50
.
Редактировать:Имена не всегда будут X-sampledataX .Я просто сделал это для примера.Таким образом, имена не могут быть зациклены.Я думаю, мне придется ввести их вручную
Пока у меня есть следующее (которое работает).Но я ищу более эффективный способ сделать это..
foreach my $line(@body){
if ($line=~ /^1-sampledata1\s/){
$line=~ s/1-ENST0000//g;
$line=~ s/\s+//g;
push (@array1, $line);
#using splitarray because i want to store data as one character each
#for ex: i wana store 'This' as T H I S in different elements of array
@splitarray1= split ('',$line);
last if ($line=~ /2-sampledata2/);
}
}
foreach my $line(@body){
if ($line=~ /^2-sampledata2\s/){
$line=~ s/2-ENSBTAP0//g;
$line=~ s/\s+//g;
@splitarray2= split ('',$line);
last if ($line=~ /3-sampledata3/);
}
}
Как вы можете видеть, у меня есть разные массивы для каждого раздела и разные циклы for для каждого раздела.Если я буду придерживаться подхода, который у меня есть до сих пор, то в итоге у меня будет 50 циклов for и 50 массивов.
Есть ли другой лучший способ сделать это?В конце концов, я действительно хочу получить 50 массивов, но не хочу писать 50 циклов for.И поскольку позже в программе я буду перебирать 50 массивов, может быть, сохранить их в виде массива?Я новичок в Perl , так что это немного ошеломляет ...
Решение
Первое, на что следует обратить внимание, это то, что вы пытаетесь использовать имена переменных с целочисленными суффиксами:Не надо.Используйте массив всякий раз, когда обнаружите, что вам хочется это сделать.Во-вторых, вам нужно прочитать содержимое файла только один раз, а не несколько.В-третьих, обычно в Perl нет веских причин рассматривать строку как массив символов.
Обновить: Эта версия кода использует наличие начальных пробелов, чтобы решить, что делать.Я также оставляю предыдущую версию для справки.
#!/usr/bin/perl
use strict;
use warnings;
my @data;
while ( my $line = <DATA> ) {
chomp $line;
if ( $line =~ s/^ +/ / ) {
push @{ $data[-1] }, split //, $line;
}
else {
push @data, [ split //, $line ];
}
}
use Data::Dumper;
print Dumper \@data;
__DATA__
1-sampledata1 This is a sample test
and data for this continues
2-sampledata2 This is sample test 2
Data for this also is on second line
Предыдущая версия:
#!/usr/bin/perl
use strict;
use warnings;
my @data;
while ( my $line = <DATA> ) {
chomp $line;
$line =~ s/\s+/ /g;
if ( $line =~ /^[0-9]+-/ ) {
push @data, [ split //, $line ];
}
else {
push @{ $data[-1] }, split //, $line;
}
}
use Data::Dumper;
print Dumper \@data;
__DATA__
1-sampledata1 This is a sample test
and data for this continues
2-sampledata2 This is sample test 2
Data for this also is on second line
Другие советы
#! /usr/bin/env perl
use strict;
use warnings;
my %data;
{
my( $key, $rest );
while( my $line = <> ){
unless( ($rest) = $line =~ /^ \s+(.*)/x ){
($key, $rest) = $line =~ /^(.*?)\s+(.*)/;
}
push @{ $data{$key} }, $rest;
}
}
Приведенный ниже код очень похож на @Брэд Гилберт's и @Sinan Unurрешения компании:
#!/usr/bin/perl
use strict;
use warnings;
use Data::Dumper;
my (%arrays, $label);
while (my $line = <DATA>)
{
($label, $line) = ($1, $2) if $line =~ /^(\S+)(.*)/; # new data block
$line =~ s/^\s+//; # strip whitespaces from the begining
# append data for corresponding label
push @{$arrays{$label}}, split('', $line) if defined $label;
}
print $arrays{'1-sampledata1'}[2], "\n"; # 'i'
print join '-', @{$arrays{'2-sampledata2'}}; # 'T-h-i-s- -i-s- -s-a-m-p-l
print Dumper \%arrays;
__DATA__
1-sampledata1 This is a sample test
and data for this continues
2-sampledata2 This is sample test 2
Data for this also is on second line
Выходной сигнал
i
T-h-i-s- -i-s- -s-a-m-p-l-e- -t-e-s-t- -2-D-a-t-a- -f-o-r- -t-h-i-s- -a-l-s-o- -i-s- -o-n- -s-e-c-o-n-d- -l-i-n-e-
$VAR1 = {
'2-sampledata2' => [
'T',
'h',
'i',
's',
' ',
'i',
's',
' ',
's',
'a',
'm',
'p',
'l',
'e',
' ',
't',
'e',
's',
't',
' ',
'2',
'D',
'a',
't',
'a',
' ',
'f',
'o',
'r',
' ',
't',
'h',
'i',
's',
' ',
'a',
'l',
's',
'o',
' ',
'i',
's',
' ',
'o',
'n',
' ',
's',
'e',
'c',
'o',
'n',
'd',
' ',
'l',
'i',
'n',
'e',
'
'
],
'1-sampledata1' => [
'T',
'h',
'i',
's',
' ',
'i',
's',
' ',
'a',
' ',
's',
'a',
'm',
'p',
'l',
'e',
' ',
't',
'e',
's',
't',
'a',
'n',
'd',
' ',
'd',
'a',
't',
'a',
' ',
'f',
'o',
'r',
' ',
't',
'h',
'i',
's',
' ',
'c',
'o',
'n',
't',
'i',
'n',
'u',
'e',
's',
'
'
]
};
Вместо этого вам следует использовать хэш-сопоставление с массивами.
Используйте этот шаблон регулярного выражения, чтобы получить индекс:
/^(\d+)-sampledata(\d+)/
И затем, с my %arrays
, делать:
push($arrays{$index}), $line;
Затем вы можете получить доступ к массивам с помощью $arrays{$index}
.