Perl 为什么for循环没有终止?
我有如下输入文件Perl 为什么for循环没有终止?,perl,Perl,我有如下输入文件 A0FGR8 659-660 659-662 A4UGR9 728-751 我希望输出为两个不同的文件(A0FGR8.diso,A4UGR9.diso),这些文件假设由数字组成 659 660 661 662 在此之后,for循环应根据上限数字终止,但事实并非如此。。 我的perl代码如下所示 #!/usr/bin/perl open(F1,"$ARGV[0]") or die; chomp(@list = <F1>); close(F1); for($i =
A0FGR8 659-660 659-662
A4UGR9 728-751
我希望输出为两个不同的文件(A0FGR8.diso,A4UGR9.diso),这些文件假设由数字组成
659
660
661
662
在此之后,for循环应根据上限数字终止,但事实并非如此。。
我的perl代码如下所示
#!/usr/bin/perl
open(F1,"$ARGV[0]") or die;
chomp(@list = <F1>);
close(F1);
for($i = 0; $i <= $#list; $i++) {
@id=split(/\s+/,$list[$i]);
open(OUT,">tmp/$id[0].diso") or die;
for($j = $id[1]; $j = $#id; $j++) {
($n1, $n2) = split(/-/, $id[$j]);
for($k = $n1; $k <= $n2; $k++) {
print OUT "$k\n";
}
}
}
#/usr/bin/perl
打开(F1,“$ARGV[0]”)或模具;
chomp(@list=);
关闭(F1);
对于($i=0;$i这里有一个用saner Perl重写的代码。所有for
循环都保证终止,因为我将它们更改为使用for
的列表版本,而不是的C风格,这是一个很好的Perl习惯,因为的列表更难出错
我还将
的最外层的更改为直接遍历列表,而不是遍历索引,因为实际上除了从列表中拉出项目之外,您没有使用索引
裸
操作符读取@ARGV
中列出的文件(如果@ARGV
为空,则从STDIN
读取),因此我更改了该操作。很少需要显式打开$ARGV[0]
最后,我将输出文件的open
更改为使用词法文件句柄和open
的三参数形式。这两种都是推荐的做法。词法文件句柄避免全局变量,并且在超出范围时自动关闭(…而且您忘记了关闭您的out
),而三个argopen
可以避免在程序外部为其指定文件名时出现安全漏洞
我还让它在严格
和警告
下干净地运行,这两种警告都应该一直使用
修订守则:
#!/usr/bin/env perl
use strict;
use warnings;
use 5.010;
my @list = <>;
chomp @list;
for my $line (@list) {
my @id = split(/\s+/, $line);
open my $outfile, '>', "tmp/$id[0].diso"
or die "Failed to open output file: $!";
for my $j ($id[1] .. $#id) {
my ($n1, $n2) = split(/-/, $id[$j]);
for my $k ($n1 .. $n2) {
say $outfile $k;
}
}
}
!/usr/bin/env perl
严格使用;
使用警告;
使用5.010;
我的@list=;
chomp@list;
对于我的$line(@list){
my@id=拆分(/\s+/,$line);
打开我的$outfile,'>',“tmp/$id[0].diso”
或“无法打开输出文件:$!”;
对于我的$j($id[1]…$#id){
my($n1,$n2)=拆分(/-/,$id[$j]);
对于我的$k($n1..$n2){
比如$outfile$k;
}
}
}
不幸的是,我不能说这是否真的适用于您的数据集,因为您没有提供任何样本数据来测试它。您的程序编写得更清楚
您没有说明是否要合并重叠范围,但您自己的代码没有尝试这样做,因此我保留了它们的原样,以便在输出到A0FGR8.diso时重复659和660
use strict;
use warnings 'all';
while ( <> ) {
my ($id, @ranges) = split;
open my $out_fh, '>', "tmp/$id.diso" or die $!;
for my $range ( @ranges ) {
my ($start, $end) = split /-/, $range;
print { $out_fh } "$_\n" for $start .. $end;
}
}
tmp/A4UGR9.diso
更新
这里有一个替代版本,使用该模块消除重叠范围内的重复值。它不是核心模块,因此您可能需要安装它
use strict;
use warnings 'all';
use Number::Range;
while ( <DATA> ) {
my ($id, @ranges) = split;
my $range = Number::Range->new;
for my $interval ( @ranges ) {
no warnings 'Number::Range';
$range->addrange( $interval =~ s/-/../r ); #/
}
open my $out_fh, '>', "$id.diso" or die $!;
print { $out_fh } "$_\n" for $range->range;
}
__DATA__
A0FGR8 659-660 659-662
$j=$#id
!=$j=$#id
!=$j第二个循环上的循环退出条件将始终返回true,因此永远不会退出。这是错误的,OP确实提供了(最小的)测试数据,因此您应该测试它
728
729
730
731
732
733
734
735
736
737
738
739
740
741
742
743
744
745
746
747
748
749
750
751
use strict;
use warnings 'all';
use Number::Range;
while ( <DATA> ) {
my ($id, @ranges) = split;
my $range = Number::Range->new;
for my $interval ( @ranges ) {
no warnings 'Number::Range';
$range->addrange( $interval =~ s/-/../r ); #/
}
open my $out_fh, '>', "$id.diso" or die $!;
print { $out_fh } "$_\n" for $range->range;
}
__DATA__
A0FGR8 659-660 659-662
659
660
661
662