我正在尝试使用foreach
循环遍历数组,然后使用嵌套的while
循环遍历文本文件的每一行,以查看数组元素是否与一行匹配文本;如果是这样,那么我将该行中的数据推送到一个新数组中以执行计算。
外部foreach
循环似乎正常工作(基于每个数组元素的打印结果),但内部while循环不循环(每次都将相同的数据推入数组)。
有什么建议吗?
代码在
之下#! /usr/bin/perl -T
use CGI qw(:cgi-lib :standard);
print "Content-type: text/html\n\n";
my $input = param('sequence');
my $meanexpfile = "final_expression_complete.txt";
open(FILE, $meanexpfile) or print "unable to open file";
my @meanmatches;
@regex = (split /\s/, $input);
foreach $regex (@regex) {
while (my $line = <FILE>) {
if ( $line =~ m/$regex\s(.+\n)/i ) {
push(@meanmatches, $1);
}
}
my $average = average(@meanmatches);
my $std_dev = std_dev($average, @meanmatches);
my $average_round = sprintf("%0.4f", $average);
my $stdev_round = sprintf("%0.4f", $std_dev);
my $coefficient_of_variation = $stdev_round / $average_round;
my $cv_round = sprintf("%0.4f", $coefficient_of_variation);
print font(
{ color => "blue" }, "<br><B>$regex average: $average_round
 Standard deviation: $stdev_round Coefficient of
variation(Cv): $cv_round</B>"
);
}
sub average {
my (@values) = @_;
my $count = scalar @values;
my $total = 0;
$total += $_ for @values;
return $count ? $total / $count : 0;
}
sub std_dev {
my ($average, @values) = @_;
my $count = scalar @values;
my $std_dev_sum = 0;
$std_dev_sum += ($_ - $average)**2 for @values;
return $count ? sqrt($std_dev_sum / $count) : 0;
}
答案 0 :(得分:1)
是的,我的建议是:
strict
和warnings
。open ( my $inputfile, "<", 'final_expression.txt' );
die
如果它没有打开 - 你的程序的其余部分是无关紧要的。 chomp $line
foreach
循环的下一次迭代,这样你的while
循环就变成了null操作。简单地说,将文件读入数组my @lines = <FILE>;
可以解决这个问题。考虑到这一点:
#!/usr/bin/perl -T
use strict;
use warnings;
use CGI qw(:cgi-lib :standard);
print "Content-type: text/html\n\n";
my $input = param('sequence');
my $meanexpfile = "final_expression_complete.txt";
open( my $input_file, "<", $meanexpfile ) or die "unable to open file";
my @meanmatches;
my @regex = ( split /\s/, $input );
my @lines = <$input_file>;
chomp (@lines);
close($input_file) or warn $!;
foreach my $regex (@regex) {
foreach my $line (@lines) {
if ( $line =~ m/$regex\s(.+\n)/i ) {
push( @meanmatches, $1 );
}
}
my $average = average(@meanmatches);
my $std_dev = std_dev( $average, @meanmatches );
my $average_round = sprintf( "%0.4f", $average );
my $stdev_round = sprintf( "%0.4f", $std_dev );
my $coefficient_of_variation = $stdev_round / $average_round;
my $cv_round = sprintf( "%0.4f", $coefficient_of_variation );
print font(
{ color => "blue" }, "<br><B>$regex average: $average_round
 Standard deviation: $stdev_round Coefficient of
variation(Cv): $cv_round</B>"
);
}
sub average {
my (@values) = @_;
my $count = scalar @values;
my $total = 0;
$total += $_ for @values;
return $count ? $total / $count : 0;
}
sub std_dev {
my ( $average, @values ) = @_;
my $count = scalar @values;
my $std_dev_sum = 0;
$std_dev_sum += ( $_ - $average )**2 for @values;
return $count ? sqrt( $std_dev_sum / $count ) : 0;
}
答案 1 :(得分:0)
这里的问题是从foreach的第二次迭代开始,你试图从已经读过的文件句柄中读取。你需要回到开头再读一遍:
foreach $regex (@regex) {
seek FILE, 0, 0;
while ( my $line = <FILE> ) {
然而,这看起来并不高效。为什么要读取文件几次,当你在foreach开始之前读取它一次,然后遍历列表:
my @lines;
while (<FILE>) {
push (@lines, $_);
}
foreach $regex (@regex) {
foreach $line (@lines) {
使用后者,您可能还需要考虑使用grep
而不是while
循环。