Perl脚本报错求助:已关闭文件句柄读取+哈希初始化错误
Perl脚本错误修复方案
错误1:readline() on closed filehandle $fh
- 原因:打开
clinical.txt时未验证文件是否成功打开,若文件不存在、路径错误或无读取权限,文件句柄$fh会处于关闭状态,后续读取操作触发报错。 - 解决方法:在
open语句后添加错误检查逻辑,确保文件正常打开:open(my $fh_clin, '<', "clinical.txt") or die "无法打开clinical.txt: $!";
错误2:Reference found where even-sized list expected
- 原因:初始化哈希时错误使用
{}(该语法用于创建匿名哈希引用),而哈希初始化需要用()传入键值对列表(空列表对应空哈希)。 - 解决方法:将哈希初始化语句中的
{}替换为():%hash = (); %tested = (); %Mut_Count = ();
完整修复后的脚本
#!/usr/bin/perl use Cwd; use warnings; use strict; # 强制变量声明,避免全局变量污染 # 读取clinical.txt并添加错误检查 open(my $fh_clin, '<', "clinical.txt") or die "无法打开clinical.txt: $!"; my (@id, @status); my $line = <$fh_clin>; # 跳过表头行 while($line = <$fh_clin>) { chomp $line; my @fields2 = split(" ", $line); push(@id, $fields2[1]); push(@status, $fields2[3]); } close($fh_clin); my @flow = grep { -d } glob "*"; my $arrSize = @flow; for (my $p = 0; $p < $arrSize; $p++) { my @files = <"$flow[$p]/*.maf">; print $flow[$p],"\n"; foreach my $file (@files) { print $file,"\n"; # 打开MAF文件,使用词法句柄并添加错误检查 open(my $fh_maf, '<', $file) or die "无法打开$file: $!"; my (%hash, %tested, %Mut_Count); # 局部哈希自动初始化为空 my $hyper = 0; # 跳过前6行注释/表头 for (1..6) { $line = <$fh_maf>; } while($line = <$fh_maf>) { chomp $line; my @temp = split("\t", $line); my $key = $temp[4]."_".$temp[5]."_".$temp[6]."_".$temp[10]."_".$temp[11]."_".$temp[12]."_".$temp[15]; push @{$hash{$key}}, "0"; push @{$Mut_Count{$temp[15]}}, "0"; } close($fh_maf); my @nm = split(/\./, $file); # 自动创建Results目录 mkdir "Results" unless -d "Results"; # 重新打开MAF文件 open($fh_maf, '<', $file) or die "无法重新打开$file: $!"; open(my $out1, ">", "Results/".$nm[1]."_Hyper.txt") or die "无法创建输出文件: $!"; # 跳过前5行 for (1..5) { $line = <$fh_maf>; } chomp $line; my @temp = split(" ", $line); my @temp2 = split(",", $temp[1]); print $out1 "Gene\tMutation\tType\tdbSNP\tStatus\tPolyphen\tSift"; for(my $j=0;$j<scalar(@id);$j++){ my @M = split('-', $id[$j]); for(my $i=0;$i<scalar(@temp2);$i++) { my @N = split('-', $temp2[$i]); if(scalar(@{$Mut_Count{$temp2[$i]}}) > 499 && $M[0] eq $N[0] && $M[1] eq $N[1] && $M[2] eq $N[2] && $status[$j] eq 'MSS') { print $out1 "\t",$temp2[$i]; $hyper++; } } } $line = <$fh_maf>; # 跳过第6行 while($line = <$fh_maf>) { chomp $line; my $hy = 0; my @temp = split("\t", $line); my $key = $temp[4]."_".$temp[5]."_".$temp[6]."_".$temp[10]."_".$temp[11]."_".$temp[12]; if(!exists $tested{$key}) { push @{$tested{$key}}, "0"; print $out1 "\n",$temp[0],"\t",$key,"\t",$temp[8],"\t",$temp[13],"\t",$temp[25],"\t",$temp[72],"\t",$temp[73]; for(my $i=0;$i<scalar(@temp2);$i++) { my $key_full = $temp[4]."_".$temp[5]."_".$temp[6]."_".$temp[10]."_".$temp[11]."_".$temp[12]."_".$temp2[$i]; my @L = split('-', $temp2[$i]); for(my $j=0;$j<scalar(@id);$j++){ my @O = split('-', $id[$j]); if(scalar(@{$Mut_Count{$temp2[$i]}}) > 499 && $L[0] eq $O[0] && $L[1] eq $O[1] && $L[2] eq $O[2] && $status[$j] eq 'MSS') { if(exists $hash{$key_full}) { print $out1 "\t1"; $hy++; } else { print $out1 "\t0"; } } } } } } close($fh_maf); close($out1); open(my $out3, ">", "Results/".$nm[1]."_Summary.txt") or die "无法创建汇总文件: $!"; print $out3 "Hypermutated\t$hyper\n"; close($out3); } }
额外优化说明
- 添加
use strict强制变量声明,避免全局变量引发的潜在问题 - 使用词法文件句柄替代裸字句柄,提升代码安全性和可读性
- 为所有文件操作添加错误检查,便于快速定位问题
- 读取文件后及时关闭句柄,避免资源泄漏
- 自动创建
Results目录,防止因目录不存在导致输出失败 - 用循环替代重复的行跳过语句,简化代码结构
- 重命名部分变量提升代码可读性
内容的提问来源于stack exchange,提问作者Aqsa Arshad.
相关产品推荐
相关产品推荐

