perl:将数据拆分为列,选择某些列,将列1作为哈希的键加载,将列2加载为哈希值

时间:2013-10-27 19:47:49

标签: regex perl hash

#!/usr/bin/perl
use strict;
use warnings;

# (1) program reads file
# (2) uses the split fxn to split the columns
# (3) loads the IDs that begin with FBgn from the 1st column as keys to a hash
# (4) loads the gene symbol from the second column as the value in each hash entry

my $infile = "fb_synonym_fb_2013_05.tsv";

open( FILE, "<", $infile )
    or die "Cannot open file $!";

my @data = <FILE>;

foreach my $line (@data) {
    my @column = split( /\s+/, $line );
    #print $column[0],"\n";
    my $columnID = $column[0];
        foreach ( my $columnID ) {
            while ( $columnID =~ /(^FBgn\d+)/ ) {
                my $ID = $1;
                print $ID, "\n";
            }
        }
 }

我尝试运行代码,但它说$ columnID是未初始化的值。我陷入了困境。我需要选择以“FBgn”

开头的列

输入: 数据文件非常大,所以这里是一个选择

##primary_FBid current_symbol current_fullname fullname_synonym(s) symbol_synonym(s)
FBtr0000004 Ecol\lacZ[svp-3]RA      lacZ[svp-3]RA
FBtr0000005 Ecol\lacZ[hkb-5953]RA       lacZ[5953]RA,lacZ[hkb-5953]RA,hkb-  lacZ,5953
FBtr0000007 Mab4A11[+]R2.1          
FBtr0000009 Ecol\lacZ[betaTub56D.AS1]RA lacZ[betaTub56D.AS1]RA
FBtr0000010 Ecol\lacZ[betaTub56D.AS2]RA lacZ[betaTub56D.AS2]RA
FBtr0000011 Ecol\lacZ[betaTub56D.AS3]RA lacZ[betaTub56D.AS3]RA
FBtr0000012 Ecol\lacZ[betaTub56D.NN]RA  lacZ[betaTub56D.NN]RA
FBtr0000013 Ecol\lacZ[betaTub56D.NC]RA  lacZ[betaTub56D.NC]RA
FBtr0000014 Ecol\lacZ[betaTub56D.CP]RA  lacZ[betaTub56D.CP]RA
FBtr0000015 Ecol\lacZ[betaTub56D.ACO]RA lacZ[betaTub56D.ACO]RA
FBtr0000016 Ecol\lacZ[betaTub56D.AC3]RA lacZ[betaTub56D.AC3]RA

3 个答案:

答案 0 :(得分:4)

我怀疑本节存在逻辑问题:

my $columnID = $column[0];
foreach ( my $columnID ) {
    while ( $columnID =~ /(^FBgn\d+)/ ) {
        my $ID = $1;
        print $ID, "\n";
    }
}

首先迭代每一行,然后将该行拆分为列。到目前为止一切都很好。

然后你拿第一列并将其放入标量$columnID。还好。值得检查是否定义了这个(如果你有一个空行)。

问题在于下一行:

foreach ( my $columnID )

你究竟在迭代什么?你声明了一个新的变量($columnID的一个新实例 - 你绝对不想这样做,因为它会隐藏你刚刚将$ columnID设置为上面的内容) - 但是......这行不能帮到你

接下来你有:

while ( $columnID =~ /(^FBgn\d+)/ ) {

... 另一个循环。但你不需要它。你只想知道这是真还是假:更好地写:

if ( $columnID =~ ... ) {
    # action if true
}

摘要:尝试将代码重写为:

my @data = <FILE>;

foreach my $line (@data) {
    my @column = split( /\s+/, $line );
    my $columnID = $column[0];
    next if ( ! defined( $columnID ) ); # bad line

    if ( $columnID =~ /(^FBgn\d+)/ ) {
        my $ID = $1;
        print $ID, "\n";
    }
}

答案 1 :(得分:0)

您必须在循环之外预先定义变量$columnID$ID以分配它们。您还定义了my $columnID两次。

尝试:

my @data = <FILE>;
my @column;
my $columnID;
my $ID;

foreach my $line (@data) {
    @column = split( /\s+/, $line );
    #print $column[0],"\n";
    $columnID = $column[0];
    if ( $columnID =~ /(^FBgn\d+)/ ) {
        $ID = $1;
        print $ID, "\n";
    }
 }

答案 2 :(得分:0)

晚会,但无论如何,这是我的答案:

#!/usr/bin/perl
use Data::Dumper;
@data = ("FBgn34  2.2  3  xxxx\n","FBgn35 20.2 30 yyyy\n");

my %hash = ();
foreach my $line (@data) {
    my @column = split( /\s+/, $line );
    if ( $column[0] =~ /(^FBgn\d+)/ ) {
        $hash{ $column[0] } = $column[1];
    }
 }
 print Dumper(\%hash);

输出:

{
    'FBgn35' => '20.2',
    'FBgn34' => '2.2'
};