Warning: file_get_contents(/data/phpspider/zhask/data//catemap/8/perl/10.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Perl 为什么for循环没有终止?_Perl - Fatal编程技术网

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
),而三个arg
open
可以避免在程序外部为其指定文件名时出现安全漏洞

我还让它在
严格
警告
下干净地运行,这两种警告都应该一直使用

修订守则:

#!/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