在Perl中读取文件并存储在数组中?

时间:2012-05-28 11:19:51

标签: arrays perl

我想读取一个文件,并根据它有多少链(M,N,O,..)来生成一些数组。

以下是文件的一部分:

SEQRES   1 M  312  ALA ALA ASP PRO LYS LEU LEU LYS ALA ALA ALA GLU ALA
SEQRES   2 M  312  SER TYR ALA PHE ALA LYS GLU VAL ASP TRP ASN ASN GLY
SEQRES   3 M  312  ILE PHE LEU GLN ALA PRO GLY LYS LEU GLN PRO LEU GLU
SEQRES   4 M  312  ALA LEU LYS ALA ILE ASP LYS MET ILE VAL MET GLY ALA
SEQRES   5 M  213  SER PHE ASN ARG ASN

SEQRES   1 N  312  ASP GLU ILE GLY ASP ALA ALA LYS LYS LEU GLY ASP ALA
SEQRES   2 N  312  SER TYR ALA PHE ALA LYS GLU VAL ASP TRP ASN ASN GLY
SEQRES   3 N  312  ILE PHE LEU GLN ALA PRO GLY LYS LEU GLN PRO LEU GLU
SEQRES   4 N  312  ALA LEU LYS ALA ILE ASP LYS MET ILE VAL MET GLY ALA
SEQRES   5 N  312  ALA ALA ASP PRO LYS LEU LEU LYS ALA ALA ALA GLU ALA
SEQRES   6 N  312  VAL THR SER ARG ALA ASP TRP ASP ASN VAL

SEQRES   1 O  312  HIS HIS LYS ALA ILE GLY SER ILE SER GLY PRO ASN GLY
SEQRES   2 O  312  SER TYR ALA PHE ALA LYS GLU VAL ASP TRP ASN ASN GLY
SEQRES   3 O  312  ILE PHE LEU GLN ALA PRO GLY LYS LEU GLN PRO LEU GLU
SEQRES   4 O  312  ALA LEU LYS ALA ILE ASP LYS MET ILE VAL

这是我的代码:

my @seq;
my $string="";
my @seqFile;
my $file=<>;
open(FILE, "$file");
while (my $line=<FILE>){
    if ($line =~ /^SEQRES/) {
        chomp $line;
        push @seq, [split (/\s+/, $line)] ;
    }
}
close(FILE);
for my $i (0..$#seq) {
    my $ob =$seq[$i][2];
    if ($seq[$i][2] eq $ob ){
        for (my $j=4;$j<=$#{$seq[$i]};$j++) {
            my $temp= $seq[$i][$j];
            $string .= $temp;
        }
        $ob = $seq[$i][2];
        last;
    }
    push @seqFile, $ob;
    push @seqFile, $string;
    $string = ''; #string needs to be empty to store new lines
}

使用上面的示例:3个数组M(:) ALAALAASP:....,N(:) ASPGLU ..,O(:) HISHISLYS ......

我设法将所有SEQRES放在一个字符串中,但这不是我想要的。

某处我需要设置if(){}并检查M <=> NN <=> O是不同的。然后保存字符串并启动字符串和数组。但它不断累积与$#seq相同字符串的次数。或者,如果我移动一个}的位置,那么它不存储任何内容,或者给我错误消息。我怎么能这样做?

2 个答案:

答案 0 :(得分:2)

你在这里看不到问题吗?

my $ob =$seq[$i][2];
if ($seq[$i][2] ne $ob ){

这类似于:

my $x = "this";
if ($x ne "this) {

if条件怎么可能是真的?

更好的方法是使用数组哈希,键入M,N或O,(你设置的是$ ob):

open (my $fh, '<', $file);   # using global globs like FILE is depreciated
my %hash_of_arrays;
while (<$fh>) {
    my @data = split;
    push @{$hash_of_arrays{$data[2]}}, join('', (@data)[4..$#data]);
}

很确定这与你想要做的很接近; push的第二个arg使用数组切片

请注意,如果@{$hash{$data[2]}}尚不存在,则会通过 autovivification 创建:http://en.wikipedia.org/wiki/Autovivification

答案 1 :(得分:1)

我认为这个程序可以满足您的需求。

我没有看第三个字段值的变化,而是写了一个空白行或文件末尾标记链的末尾。

use strict;
use warnings;

my $file = 'seq.txt';

open my $fh, '<', $file or die $!;

my @seqFile;
my $string;
my $ob;

while (<$fh>) {
  if (/^SEQRES/) {           
    my @data = split;
    $string .= join '', @data[4..$#data];
    $ob = $data[2];
  }
  if (eof($fh) or not /\S/) {
    push @seqFile, $ob, $string;
    $ob = $string = undef;
  }
}

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

<强>输出

$VAR1 = [
          'M',
          'ALAALAASPPROLYSLEULEULYSALAALAALAGLUALASERTYRALAPHEALALYSGLUVALASPTRPASNASNGLYILEPHELEUGLNALAPROGLYLYSLEUGLNPROLEUGLUALALEULYSALAILEASPLYSMETILEVALMETGLYALASERPHEASNARGASN',
          'N',
          'ASPGLUILEGLYASPALAALALYSLYSLEUGLYASPALASERTYRALAPHEALALYSGLUVALASPTRPASNASNGLYILEPHELEUGLNALAPROGLYLYSLEUGLNPROLEUGLUALALEULYSALAILEASPLYSMETILEVALMETGLYALAALAALAASPPROLYSLEULEULYSALAALAALAGLUALAVALTHRSERARGALAASPTRPASPASNVAL',
          'O',
          'HISHISLYSALAILEGLYSERILESERGLYPROASNGLYSERTYRALAPHEALALYSGLUVALASPTRPASNASNGLYILEPHELEUGLNALAPROGLYLYSLEUGLNPROLEUGLUALALEULYSALAILEASPLYSMETILEVAL'
        ];

修改

既然我知道数据文件没有空行来描绘链条,我的原始解决方案将无效。

此备选方案检查记录的第二个字段中的序列号,并在该数字为1时启动新链。每当新链开始时,也必须保存累积链,并且也可以在文件结束后保存。读循环退出。

此程序的输出与上面显示的相同。

use strict;
use warnings;

my $file = 'seq.txt';

open my $fh, '<', $file or die $!;

my @seqFile;
my $chain;
my $ob;

while (<$fh>) {

  next unless /^SEQRES/;

  my @data = split;
  if ($data[1] == 1) {
    push @seqFile, $ob, $chain if $chain;
    $ob = $chain = undef;
  }
  $chain .= join '', @data[4..$#data];
  $ob = $data[2];
}

push @seqFile, $ob, $chain if $chain;

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