无法在未定义的值上调用方法“print”

时间:2016-10-25 09:47:30

标签: perl

无法在第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;
}

我尝试了多种变体,但它们似乎都没有效果。有任何想法吗?

3 个答案:

答案 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);