2013-02-22 2 views
1

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

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

Вот упрощенная версия файла, который создает массив:

#!/usr/bin/perl 

use strict; 
use warnings; 
use CLASS::DATATYPE; 

my $foundheaders = 0; 
my $array_elem = 0; 
my @MY_ARRAY =(); 

open FH, '<', "dummy.txt"; 
# open FH, '<', "$ARGV[0]"; 

while (my $line = <FH>) { 
    # once you've found the headers, this will begin to kickoff 
    if ($foundheaders == 1) 
    { 
     # get line elements and create a new DATATYPE object using the elements 
     # matched to the header index 
     my @lineArray = split("\t", $line); 
     my $thisdata = new CLASS::DATATYPE(); 

     $thisdata->FIRSTVAL(@lineArray[$HEADERS::FIRST]); 
     $thisdata->SECONDVAL(@lineArray[$HEADERS::SECOND]); 

     print "$thisdata\n"; 

     # Add new DATATYPE to the array 
     $MY_ARRAY[$array_elem] = $thisdata; 
     $array_elem ++; 
    }; 

    # Search for line with "#R" at the beginning. This will contain the headers 
    if ($line =~ m/#R/) { 
     # strip the first # symbol from the headers 
     my $subline = substr $line, 1; 
     chomp($subline); 

     # split the line into an array and index headers 
     my @headers = split("\t", $subline); 
     &assign_headers(\@headers); 

     # check off foundheaders flag 
     $foundheaders = 1; 
    }; 
}; 
close FH; 

# test output value 
my $test = $MY_ARRAY[2]->SECONDVAL(); 
print "$test\n"; 

1; 

sub assign_headers 
{ 
    package HEADERS; 
    my @array = @{$_[0]}; 
    my $iter = 0; 

    # check each array loop against known headers and assign the array index to header 
    foreach (@array) 
    { 
     if ($_ eq "ROW1") 
     { 
      our $FIRST = $iter; 
     }; 

     if ($_ eq "ROW2") 
     { 
      our $SECOND = $iter; 
     }; 
     $iter++; 
    } 
} 

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

Вот DATATYPE пакет хранится в папке КЛАССА:

#!/usr/bin/perl 

package CLASS::DATATYPE; 

use strict; 
use warnings; 

sub new { 
    my $self = {}; 
    $self->{FIRSTVAL} = undef; 
    $self->{SECONDVAL} = undef; 
    $self->{THIRDVAL} = undef; 
    bless($self); 
    return $self; 
} 

sub FIRSTVAL { 
    my $self = shift; 
    if (@_) { $self->{FIRSTVAL} = shift } 
    return $self->{FIRSTVAL}; 
} 

sub SECONDVAL { 
    my $self = shift; 
    if (@_) { $self->{SECONDVAL} = shift } 
    return $self->{SECONDVAL}; 
} 

1; 

Я использовал произвольный фиктивный файл, ничего с совпадающей строкой заголовка будет работать:

## blah blah blah 
## blah blah blah 
#ROWS ROW1 ROW2 ROW3 
1 fwewef aewf sfd8y9 
2 gereer few79 dfsui 
3 svfsg789 aferw789 uifdgs 
4 dfsgy 78fer fds 
5 78fgds sdf78y sfdgh 

И вызывающий файл будет что-то вроде следующего, передавая входной файл и получая выход:

#!/usr/bin/perl 

use strict; 
use warnings; 
use CLASS::DATATYPE; 

my $file = "dummy.txt"; 

our @RESULTS = `/usr/bin/perl my_reader.pl $file`; 

my $test = $RESULTS[2]->SECONDVAL(); 
print "$test\n"; 
+1

Сократите представления и четко изложить свои вопрос. Прямо сейчас, это, скорее всего, TL, DR для большинства людей. – speakr

+1

Ваш код очень не идиоматичен, и на самом деле очень мало. Весь смысл обработки файла в структуре памяти заключается в том, что его можно легко сработать, и нет причин, по которым его не следует ставить в начале основной программы. Это какое-то упражнение? Ваш класс совершенно не нужен - ваши данные - это всего лишь массив массивов. – Borodin

+0

В ответ на Бородин: Обоснованием этого было бы два разных типа входных файлов (vcf и maf), каждый из которых имел бы разные заголовки, которые следует использовать в общем типе данных для обработки. Я должен сделать класс, чтобы справиться с этим. – user2101090

ответ

1

Единственный способ объяснить, что я имею в виду, это написать программу для вас.

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

Я пошел с классом по вашему выбору, но все, что вы написали, это класс, который реализует хеш-стиль Perl.

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

Единственное важное дополнение, которое я сделал, это использовать модуль List::MoreUtils для функции firstidx. Он возвращает индекс первого элемента списка, который соответствует данному тесту. Это не основной модуль и может потребоваться установка. Если вы действительно не можете установить новые модули, то просто написать эквивалентную функцию в программе. Вернитесь, если вам нужна помощь.

Примечание Я обновил код, чтобы удалить зависимость от этого модуля, на всякий случай.

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

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

#!/usr/bin/perl 

use strict; 
use warnings; 

use Class::DataType; 

sub firstidx { 
    my ($match, $list) = @_; 
    for my $i (0 .. $#$list) { 
    return $i if $list->[$i] eq $match; 
    } 
} 

sub read_vcf { 

    my ($filename) = @_; 

    open my $fh, '<', $filename or die qq{Unable to open "$filename" for input: $!}; 

    my @columns; 
    my @data; 

    while (my $line = <$fh>) { 
    chomp $line; 
    if (@columns) { 
     my @fields = split /\t/, $line; 
     my $thisdata = Class::DataType->new(@fields[@columns]); 
     push @data, $thisdata; 
    } 
    elsif ($line =~ s/^#(?=R)//) { 
     my @headers = split /\t/, $line; 
     @columns = map firstidx($_, \@headers), qw/ ROW1 ROW2 /; 
    } 
    } 

    return \@data; 
} 

my $filename = 'dummy.txt'; 
my $results = read_vcf($filename); 

my $test = $results->[2]->secondval; 
print "$test\n"; 

И код Class::DataType в Class/DataType.pm

package Class::DataType; 

use strict; 
use warnings; 

sub new { 
    my $package = shift; 
    $package = ref $package if ref $package; 
    my $self = {}; 
    @$self{qw/ firstval secondval thirdval /} = @_; 
    bless $self, $package; 
} 

sub firstval { 
    my $self = shift; 
    my $retval = $self->{firstval}; 
    $self->{firstval} = shift if @_; 
    return $retval; 
} 

sub secondval { 
    my $self = shift; 
    my $retval = $self->{secondval}; 
    $self->{firstval} = shift if @_; 
    return $retval; 
} 

sub thirdval { 
    my $self = shift; 
    my $retval = $self->{thirdval}; 
    $self->{firstval} = shift if @_; 
    return $retval; 
} 

1; 

выходного

С данными вы дали, это печатает

svfsg789 
+0

спасибо, смог создать класс драйвера для извлечения значений. Поэтому я думаю, что, помимо исправления структуры кода, мне нужно было сделать код создания массива в суб, а затем использовать требование в вызывающем. – user2101090

+0

Нет, это неправильный выбор. 'require' редко бывает правильным выбором. Почему вы так отчаянно пытаетесь поместить свой код в отдельные файлы? – Borodin

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