无法在第40行第2行中的未定义值上调用方法打印。
这是代码。我使用FileHandle来解决文件:
#!/usr/bin/perl
use strict;
use warnings;
use FileHandle;
die unless (@ARGV ==4|| @ARGV ==5);
my @input =();
$input[0]=$ARGV[3];
$input[1]=$ARGV[4] if ($#ARGV==4);
chomp @input;
$input[0] =~ /([^\/]+)$/;
my $out = "$1.insert";
my $lane= "$1";
my %fh=();
open (Info,">$ARGV[1]") || die "$!";
open (AA,"<$ARGV[0]") || die "$!";
while(<AA>){
chomp;
my @inf=split;
my $iden=$inf[0];
my $outputfile="$ARGV[2]/$iden";
$fh{$iden}=FileHandle->new(">$outputfile");
}
close AA;
foreach my $input (@input) {
open (IN, "<$input" ) or die "$!" ;
my @path=split (/\//,$input);
print Info "#$path[-1]\n";
while (<IN>) {
my $line1 = $_;
my ($id1,$iden1) = (split "\t", $line1)[6,7];
my $line2 = <IN> ;
my ($id2,$iden2) = (split "\t", $line2)[6,7];
if ($id1 eq '+' && $id2 eq '-') {
my @inf=split(/\t/,$line1);
$fh{$iden1}->print($line1);
$fh{$iden2}->print($line2);
}
}
close IN;
}
我尝试了多种变体,但它们似乎都没有效果。有任何想法吗?
答案 0 :(得分:2)
请记住,Stack Overflow帖子的主要价值不在于解决您的特定问题,而是为了帮助成千上万可能以相同方式陷入困境的其他人。考虑到这一点,“我修复它,谢谢,再见”不仅仅是一点点自私
正如我在评论中所说,直接在哈希元素上使用open
比涉及FileHandle
要好得多。 Perl将自动生成哈希元素并为您创建一个文件句柄,大多数熟悉Perl的人都会感谢您没有在FileHandle
文档上再次阅读它们
我重写了这样的代码,这更像是Perlish并且更少依赖于“魔术数字”来访问@ARGV
。您应该将@ARGV
分配给已命名的标量列表,或者 - 更好的是 - 使用Getopt::Long
以便无论如何命名它们
您应该open
文件处理为延迟,close
输出 处理初。通过使用词法文件句柄并将其范围限制为块,可以最轻松地实现这一点。当Perl超出范围时,Perl将隐式关闭词法句柄
chomp
除了可以在奇怪和错误的情况下被调用之外,@ARGV
的内容不需要$input[0] =~ /([^\/]+)$/
,在这种情况下你需要做一个地狱更多来验证输入
您永远不会使用$out
或变量$lane
和#!/usr/bin/perl
use strict;
use warnings 'all';
# $ARGV[0] -- input file
# $ARGV[1] -- output log file
# $ARGV[2] -- directory for outputs per ident
# $ARGV[3] -- 1, $input[0]
# $ARGV[4] -- 2, $input[1] or undef
die "Fix the parameters" unless @ARGV == 4 or @ARGV == 5;
my @input = @ARGV[3,4];
my %fh;
{
open my $fh, '<', $ARGV[0] or die $!;
while ( <$fh> ) {
my $id = ( split )[0];
my $outputfile = "$ARGV[2]/$id";
open $fh{$id}, '>', $outputfile or die qq{Unable to open "$outputfile" for output: $!};
}
}
open my $log_fh, '>', $ARGV[1] or die qq{Unable to open "$ARGV[1]" for output: $!};
for my $input ( @input ) {
next unless $input; # skip unspecified parameters
my @path = split qr|/|, $input; # Really should be done by File::Spec
print $log_fh "#$path[-1]\n"; # Or File::Basename
open my $fh, '<', $input or die qq{Unable to open "$input" for input: $!};
while ( my $line0 = <$fh> ) {
chomp $line0;
my $line1 = <$fh>;
chomp $line1;
my ($id0, $iden0) = (split /\t/, $line0)[6,7];
my ($id1, $iden1) = (split /\t/, $line1)[6,7];
if ( $id0 eq '+' and $id1 eq '-' ) {
$fh{$_} or die qq{No output file for "$_"} for $iden0, $iden1;
print { $fh{$iden0} } $line0;
print { $fh{$iden1} } $line1;
}
}
}
while ( my ($iden, $fh) = each %fh ) {
close $fh or die qq{Unable to close file handle for "$iden": $!};
}
的结果,因此我将其删除了
{{1}}
答案 1 :(得分:1)
您在这一行上没有任何错误处理:
$fh{$iden}=FileHandle->new(">$outputfile");
打开文件句柄可能会无声地失败,并且只在您尝试打印文件句柄时产生错误。例如,如果您指定了无效的文件名。
此外,您永远不会检查$iden1
和$iden2
是否是实际存在的打开文件句柄的名称。可能其中一个不存在。< / p>
特别是,您无法从$line1
移除换行符,因此如果$iden1
和$iden2
恰好是该行的最后一个值,则会包含在您尝试使用的名称,它将失败。
答案 2 :(得分:1)
在第一个while
循环中,您设置了一个文件句柄的哈希值,稍后您将对其进行编写。此哈希中的键是&#34; iden&#34;传递给程序的第一个文件中的字符串。
稍后,您解析另一个文件并使用&#34; iden&#34;该文件中的值,用于选择将数据写入的文件句柄。但是一个(或多个)&#34; iden&#34;第一个文件中缺少第二个文件中的值。因此无法在%fh
哈希中找到文件句柄。因为你没有检查它,你会从哈希中得到'undef,你不能打印到一个未定义的文件句柄。
要修复它,请在尝试使用%fh
哈希中的一个文件句柄之前进行检查。
die "Unknown fh identifier '$iden1'" unless exists $fh{$iden1};
die "Unknown fh identifier '$iden2'" unless exists $fh{$iden2};
$fh{$iden1}->print($line1);
$fh{$iden2}->print($line2);