我输入文件如下......
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";
}
}
}
请告诉我我犯了哪些错误并解决了同样的错误。
答案 0 :(得分:1)
这是在更健全的Perl中重写代码。所有for
循环都保证终止,因为我将它们更改为使用for
的列表版本而不是C样式for
,这是一个良好的Perl习惯,因为列表 - {{1 很多更难以出错。
我还更改了最外面的for
来直接遍历列表,而不是循环遍历索引,因为除了从列表中拉出项目之外,你实际上并没有使用索引。
裸for
运算符从<>
中列出的文件中读取(如果@ARGV
为空,则从STDIN
中读取),因此我对其进行了更改。很少需要明确@ARGV
。
最后,我更改了输出文件的open $ARGV[0]
以使用词法文件句柄和open
的三参数形式。两者都是推荐的做法。词法文件句柄避免使用全局变量,当它们超出范围时会自动关闭(...而您忘记了open
close
...),而3-arg OUT
则避免了安全漏洞给它的文件名来自程序之外。
我还让它在open
和strict
下干净利落地运行,两者都应该始终 warnings
。
修订后的代码:
use
不幸的是,我无法说明这是否会对您的数据集实际正常工作,因为您没有提供任何样本数据来对其进行测试。
答案 1 :(得分:1)
你的程序写得更清晰
你没有说你是否想要组合重叠范围,但是你自己的代码没有尝试这样做,所以我把它们保留原样,这样659和660在输出中重复到{{1 }}
A0FGR8.diso
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/A0FGR8.diso
659
660
659
660
661
662
tmp/A4UGR9.diso
这是使用Number::Range
模块消除重叠范围内重复值的替代版本。它不是核心模块,因此您可能需要安装它
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
tmp/A0FGR8.diso