【问题标题】:Undefined subroutines &main error in PerlPerl 中未定义的子例程和主要错误
【发布时间】:2017-06-20 05:36:26
【问题描述】:

我正在尝试从这个 FASTA 文件中提取一个 DNA 序列到每行指定长度的碱基,比如 40 个。

> sample dna  (This is a typical fasta header.)
agatggcggcgctgaggggtcttgggggctctaggccggccacctactgg
tttgcagcggagacgacgcatggggcctgcgcaataggagtacgctgcct
gggaggcgtgactagaagcggaagtagttgtgggcgcctttgcaaccgcc
tgggacgccgccgagtggtctgtgcaggttcgcgggtcgctggcgggggt

使用这个 Perl 模块 (fasta.pm):

package fasta;
use strict;

sub read_fasta ($filename) {
    my $filename = @_;
    open (my $FH_IN, "<", $filename) or die "Can't open file: $filename $!";
    my @lines = <$FH_IN>;
    chomp @lines;
    return @lines;
}

sub read_seq (\@lines) {
    my $linesRef = @_;
    my @lines = @{$linesRef};
    my @seq;
    foreach my $line (@lines) {
        if ($line!~ /^>/) {
            print "$line\n";
            push (@seq, $line);
        }
    }
    return @seq;
}

sub print_seq_40 (\@seq) {
    my $linesRef = @_;
    my @lines = @{$linesRef};
    my $seq;
    foreach my $line (@lines) {
        $seq = $seq.$line;
    }

    my $i= 0;
    my $seq_line;
    while (($i+1)*40 < length ($seq)) {
        my $seq_line = substr ($seq, $i*40, 40);
        print "$seq_line\n";
        $i++;
    }
    $seq_line = substr ($seq, $i*40);
    print "$seq_line\n";
}
1;

主脚本是

use strict;
use warnings;
use fasta;

print "What is your filename: ";
my $filename = <STDIN>;
chomp $filename;

my @lines = read_fasta ($filename);
my @seq = read_seq (\@lines);
print_seq_40 (\@seq);
exit;

这是我得到的错误

Undefined subroutine &main::read_fasta called at q2.pl line 13, <STDIN> line 1.

谁能告诉我我做错了什么?

【问题讨论】:

  • 您需要在对 fasta.pm 中的函数的调用前加上“fasta::” - 即写入 fasta::read_fasta($filename) 等 - 或者您需要将 fasta.pm 更改为导出您希望不带前缀可用的功能。
  • 通常只有 Perls 自己的包以小写字符开头,因此您可能需要重命名您的 .pm。
  • 最后,看看 BioPerl 解析/生成生物信息学相关格式可能值得您花时间:bioperl.org
  • 最后一部分应该可以工作。使用 Fasta:: 显式调用有效并且一直对我有用。请为此发布特定的错误消息。
  • Fasta:: 部分的错误信息已在帖子中更新

标签: perl bioinformatics subroutine fasta


【解决方案1】:

看起来你对此一无所知。

我认为您选择使用模块和子例程有点奇怪,因为您只调用每个子例程一次并且对应的代码确实很少。

您的程序和模块都需要以use strictuse warnings 开头,并且不能在Perl 子例程中使用这样的原型。包括许多其他错误,这更接近您需要的代码。

package Fasta;

use strict;
use warnings;
use 5.010;
use autodie;

use base 'Exporter';

our @EXPORT = qw/ read_fasta read_seq print_seq_40 /;

sub read_fasta {
  my ($filename) = @_;

  open my $fh_in, '<', $filename;
  chomp(my @lines = <$fh_in>);

  @lines;
}

sub read_seq {
  my ($lines_ref) = $_[0];

  grep { not /^>/ } @$lines_ref;
}

sub print_seq_40 {
  my ($lines_ref) = @_;

  print "$_\n" for unpack '(A40)*', join '', @$lines_ref;
}

1;

q2.pl

use strict;
use warnings;

use Fasta qw/ read_fasta read_seq print_seq_40 /;

print "What is your filename: ";
my $filename = <STDIN>;
chomp $filename;

my @lines = read_fasta($filename);
my @seq = read_seq(\@lines);
print_seq_40(\@seq);

【讨论】:

    【解决方案2】:

    您需要:

    • 添加到您的模块:

      use Exporter;
      our @EXPORT = qw ( read_fasta
                         read_seq ); #etc.
      
    • 显式调用远程模块中的代码:

      fasta::read_fasta();
      
    • 显式导入模块子:

      use fasta qw ( read_fasta );
      

    另外:模块的一般约定是将模块名称的第一个字母大写。

    【讨论】:

    • 我尝试了一些建议,但仍然不起作用。在帖子中更新。
    • 啊,是的。再次查看,您的函数定义不正确。失去原型设计,如果您要从@_ 分配一些东西,您需要在列表上下文中进行。例如。 my ( $lines_ref ) = @_; - 否则它只会成为 @_ 中元素的计数
    【解决方案3】:

    在 Perl 中,如果您 use fasta;,这不会自动将其所有方法导出到程序的命名空间中。改为调用 fasta::read_fasta。

    或者:使用Exporter 自动导出方法或启用use Fasta qw/read_fasta/ 之类的东西。

    例如:

    package Fasta;
    require Exporter;
    our @ISA = qw(Exporter);
    our @EXPORT_OK = qw/read_fasta read_seq read_seq40/;
    

    使用方法:

    use Fasta qw/read_fasta read_seq read_seq40/;
    

    您也可以让 Fasta 自动导出所有方法或定义关键字来分组方法,尽管后者在过去给我带来了一些问题,只有在您确定它值得麻烦时,我才会推荐它。

    如果你想让所有方法都可用:

    package Fasta;
    use Exporter;
    our @ISA = qw(Exporter);
    our @EXPORT = qw/read_fasta read_seq read_seq40/;
    

    注意@EXPORT 不是@EXPORT_OK。后者允许稍后导入它们(就像我一样),前者自动导出所有。我链接到的文档说明了这一点。

    我刚刚注意到别的东西。您正在将 @_ 扁平化为 read_fasta 中的 $filename。我不确定这是否有效。试试这个:

    sub read_fasta {
       my $filename = $_[0]; # or ($filename) = @_; @_ is an array. $filename not.
    }
    

    解释问题:$filename = @_; 表示:将@_(一个数组)存储到 $filename(一个标量)中。 Perl 以这种方式做到这一点:数组长度存储在 $filename 中。那不是你想要的。你想要数组的第一个元素。那将是 $_[0]。

    添加了可能需要的 @ISA 或使用 Borodir 的评论。

    【讨论】:

    • 我尝试使用 Exporter 但仍然出现同样的错误。在我的帖子中更新。
    • 使用@EXPORT_OK@EXPORT。相应地导入。我更新了我的答案以包含 @EXPORT 方法。
    • 我完全按照您在 pm 文件和主脚本中的建议,但仍然收到错误消息。这两个文件都在同一个目录中,我将 fasta.pm 重命名为 Fasta.pm。这可能是导致此错误的其他原因吗?
    • 尝试使用our @EXPORT_OK,我没有从文档中获取它,但我通常这样做。另外,Fasta 之后的换行符让我很困惑,你为什么把它放在那里:/ 只是为了确定:包名和文件必须始终相同。
    • 这是误导。您还需要将Exporter 添加到@ISA 数组中,因此use base 'Exporter' 优于require。另外,子程序原型不正确,模块应该以use strictuse warnings开头。
    猜你喜欢
    • 2018-10-15
    • 2013-08-13
    • 1970-01-01
    • 2015-10-22
    • 1970-01-01
    • 1970-01-01
    • 2011-10-08
    • 2016-08-29
    • 2017-02-25
    相关资源
    最近更新 更多