-3

我需要帮助调试下面显示的代码。我已经问过这个问题的类似版本,但我无法开发出一个有效的脚本。我的输入文件是这样的:

line1
AAAAAAAAAAAAAAA
line2
BBBBBBBBBBBBBBB
line3
CCCCCCCCCCCCCCCC
line4
DDDDDDDDDDDDDDD

我希望脚本随机打乱文件中的行,例如:

line2
BBBBBBBBBBBBBBB
line1
AAAAAAAAAAAAAAA
line4
DDDDDDDDDDDDDDD
line3
CCCCCCCCCCCCCCC

该文件中有很多行(〜1,000,000)。目前,我收到以下错误:

Global symbol "$header_size" requires explicit package name at fasta_corrector9.pl line 40.

Global symbol "$header_size" requires explicit package name at fasta_corrector9.pl line 47.

我不明白如何给出$header_size明确的包名。我不是程序员,所以我需要非常基本的解释。提前致谢。

#! /usr/bin/perl

use strict;
use warnings;

print "Please enter filename (without extension): ";
my $input = <>;
chomp($input);

print "Please enter total no. of sequence in fasta file: ";
my $orig_size = <> * 2 - 1;
chomp($orig_size);

open(INFILE, "$input.fasta") or die "Error opening input file for shuffling!";
open(SHUFFLED, ">" . "$input" . "_shuffled.fasta")
    or die "Error creating shuffled output file!";

my @array  = (0);    # Need to initialise 1st element in array1&2 for the shift function
my @array2 = (0);
my $i      = 1;
my $index  = 0;
my $index2 = 0;

while (my @line = <INFILE>) {
    while ($i <= $orig_size) {

        $array[$i] = $line[$index];
        $array[$i] =~ s/(.)\s/$1/seg;

        $index++;
        $array2[$i] = $line[$index];
        $array2[$i] =~ s/(.)\s/$1/seg;

        $i++;
        $index++;
    }
}

my $array  = shift(@array);
my $array2 = shift(@array2);
for $i (reverse 0 .. $header_size) {
    my $j = int rand($i + 1);
    next if $i == $j;
    @array[$i,  $j] = @array[$j,  $i];
    @array2[$i, $j] = @array2[$j, $i];
}

while ($index2 <= $header_size) {
    print SHUFFLED "$array[$index2]\n";
    print SHUFFLED "$array2[$index2]\n";
    $index2++;
}
close(INFILE);
close(SHUFFLED);
4

3 回答 3

3

使用该大小的文件执行此操作的最简单方法是使用Tie::File允许随机访问数据文件的行

O_RDWR如果文件不存在,则使用阻止创建文件的模式

此外,shuffle函数 fromList::Util将允许您随机重新排序原始文件记录的索引

use strict;
use warnings;

use Tie::File;
use Fcntl 'O_RDWR';
use List::Util 'shuffle';

tie my @source, 'Tie::File', $ARGV[0], mode => O_RDWR, autochomp => 0
    or die "Unable to open file '$ARGV[0]': $!";

for my $line (shuffle 1 .. @source/2) {
  printf "line %d\n", $line;
  print $source[$line * 2 - 1];
}

这个程序应该运行为

perl shuffle.pl infile > outfile
于 2012-09-19T17:49:13.430 回答
3

简而言之,您$header_size在代码中使用,但没有告诉 Perl $header_size究竟是什么。这正是强烈use strict;推荐的原因,否则它会被默默地视为未定义的值(在数字上下文中为 0)。

perldoc perldiag有助于理解此类消息:

全局符号“%s”需要明确的包名

(F) 你说过“ use strict”或“ use strict vars”,这表示所有变量必须是词法范围的(使用“ my”或“ state”),事先使用“ our”声明,或者明确限定全局变量在哪个包中(使用“ ::”)。

将此应用于手头的问题,$header_size尚未初始化。在这种情况下要做的事情是my $header_size = $some_value;在使用它之前进行分配,或者只是my $header_size;如果您真的想不定义它。

于 2012-09-19T17:44:14.103 回答
2

根据您的脚本名称 (fasta_corrector9.pl) 和文件格式,我将假设您正在使用 FASTA 序列进行操作。如果这是真的,我认为你应该真正了解 CPAN 上的 Bio 命名空间。拥有这些开放格式规范的全部意义在于人们编写工具来操作格式并免费提供给您。在这种情况下,您应该强烈考虑使用Bio::DB::Fasta来访问您的 FASTA 文件作为结构化数据。

my $stream  = Bio::DB::Fasta->new('/path/to/files')->get_PrimarySeq_stream;
while (my $seq = $stream->next_seq) {
     # now you are streaming through your FASTA sequences in order.
     # You can accomplish shuffling with O(1) space complexity in this loop. 
 }
于 2012-09-19T17:50:51.323 回答