如果输入文件不为空,则仅打开输出文件

时间:2013-08-12 10:18:25

标签: perl

我有一个脚本,我在其中询问用户是否要输入文件。如果他这样做&该文件不是空的,我想使用此文件并打开输出文件的结果。我想重复这个问题3次,以便用户可以导入最多3个文件。这就是我的脚本的样子:

(12) my $genes1;
(13) my $genes2;
(14) my $genes3;

(16) if (prompt_yn("Do you want to import a genelist for filtering?")){
(17)      my $genelist1 = prompt("Give the name of the first genelist file:\n");
(18)      print "genelist1 = \"$genelist1\"\n";
(19)      open($genes1,'<',$genelist1) or die "Could not open file $genelist1 $!";
(20)      if (prompt_yn("Do you want to import another gene list file?")){
(21)           my $genelist2 = prompt("Give the name of the second genelist file:\n");
(22)           print "genelist2 = \"$genelist2\"\n";
(23)           open($genes2,'<',$genelist2) or die "Could not open file $genelist2 $!";
(24)           if (prompt_yn("Do you want to import another gene list file?")){
(25)                 my $genelist3 = prompt("Give the name of the third genelist file:\n");
(26)                 print "genelist3 = \"$genelist3\"\n";
(27)                 open($genes3,'<',$genelist3) or die "Could not open file $genelist3 $!";
(28)           }
(29)      }
(30) }
(32) print "genes1 = \"$genes1\"\n";
(33) print "genes2 = \"$genes2\"\n";
(34) print "genes3 = \"$genes3\"\n";
(45) my $genelist1filter;
(46) my $genelist1restfilter;
(47) my $genelist2filter;
(48) my $genelist2restfilter;
(49) my $genelist3filter;
(50) my $genelist3restfilter;
(51) printf "At line %d\n", __LINE__;
(52) print "genes1 is ", defined $genes1 ? "defined\n" : "not defined\n";
(53) print "genes2 is ", defined $genes2 ? "defined\n" : "not defined\n";
(54) print "genes3 is ", defined $genes3 ? "defined\n" : "not defined\n";
(56) if (-e $genes1 && -s $genes1){
(57)    printf "At line %d\n", __LINE__;
(58)    open($genelist1filter, '+>', "genelist1_missense_nonsense_frameshift_inframe_startloss_stoploss.txt") || die "Can't write new file: $!"; printf "At line %d\n", __LINE__;
(59)    #first output file
(60)    open($genelist1restfilter, '+>', "notingenelist_missense_nonsense_frameshift_inframe_startloss_stoploss.txt") || die "Can't write new file: $!"; #second output file
(61) } # same for $genes2 and $genes3
(62) printf "At line %d\n", __LINE__;

# line56 to 62 is repeated for $genes2(lines63-69) and for $genes3(lines70-77)

(183)# genelist2 filtering 
     my %hash2=();
     while(<$genes2>){
     chomp;
     #next unless -z $_;
     my $keyfield = $_;
     $hash2{$keyfield}++;
(190) }

(201)# genelist3 filtering 
     my %hash3=();
     while(<$genes3>){
     chomp;
     #next unless -z $_;
     my $keyfield = $_;
     $hash3{$keyfield}++;
(208) }

现在,当我测试这个脚本并让用户输入1个基因列表时(对于第一个问题'和'提供名称'是'是')&amp;然后回答'否'到第二个问题),我得到的信息是在$genes2$genes3附近的-e中使用了一个单位化值。我想-e-s有问题来检查文件是否存在且不为空?有人会对此发表评论吗?

这是输出的样子(基于AndrianHHH编辑的脚本)

Do you want to import a genelist for filtering? (Y/N): y
Give the name of the first genelist file:
genelist1.txt
genelist1 = "genelist1.txt"
Do you want to import another gene list file? (Y/N): n
genes1 = "GLOB(0x134c568)"
Use of uninitialized value $genes2 in concatenation (.) or string at filtering.pl line 33, <STDIN> line 3.
genes2 = ""
Use of uninitialized value $genes3 in concatenation (.) or string at filtering.pl line 34, <STDIN> line 3.
genes3 = ""
At line 51 
genes1 is defined
genes2 is not defined
genes3 is not defined
At line 57
At line 58
At line 62
Use of uninitialized value $genes2 in -e at filtering.pl line 63, <STDIN> at line 3                                                                                                       At line 69
Use of uninitialized value $genes3 in -e at filtering.pl line 70, <STDIN> line 3.
At line 77
Use of uninitialized value $genes2 in <HANDLE> at filtering.pl line 185.
readline() on unopened filehandle at filtering.pl line 185.
Use of uninitialized value $genes3 in <HANDLE> at filtering.pl line 203.
readline() on unopened filehandle at filtering.pl line 203.

2 个答案:

答案 0 :(得分:1)

尝试将if (-e -s $genes1){重写为if (-e $genes1 && -s $genes1){

-e-s文件测试返回1表示true,''表示false,如果文件不存在则返回未定义的值。原始代码似乎等同于(例如)my $a=1; my $b=1; if($a $b) {,这可能不是预期的。此外,省略-e或 - s的参数可使其在$_上运行。因此建议在这个答案的第一行重写。

如上所述进行更改,似乎$genes1未定义。但鉴于上面的open ... or die ...,这看起来不太可能。

我会在Perl调试器中运行程序,或者在测试之前添加一个这样的语句:

print "genes1 is ", defined $genes1 ? "defined\n" : "not defined\n";

更新

您提供的代码似乎可以正常使用Perl,其中perl -v报告这是为MSWin32-x64多线程构建的perl 5,版本16,subversion 3(v5.16.3)。由于问题中的代码不完整,我在问题prompting multiple questions to user (yes/no & file name input)的答案中添加了 amon 编写的提示代码。我还添加了一些print语句来显示代码中的流程。最后,我更改了第一组嵌套if语句的缩进,以更清楚地显示结构。

请检查问题中的代码是否是您正在运行的代码的真实副本。另请检查您使用的提示代码是否不会修改$genes1变量。

use strict;
use warnings;

my ($genes1, $genes2, $genes3);

if (prompt_yn("Do you want to import a genelist for filtering?")){ #prompt_yn is a subroutine which I already tested & it worked
    my $genelist1 = prompt("Give the name of the first genelist file:\n");
    print "genelist1 = \"$genelist1\"\n";
    open($genes1,'<',$genelist1) or die "Could not open file $genelist1 $!";
    if (prompt_yn("Do you want to import another gene list file?")){
        my $genelist2 = prompt("Give the name of the second genelist file:\n");
        print "genelist2 = \"$genelist2\"\n";
        open($genes2,'<',$genelist2) or die "Could not open file $genelist2 $!";
        if (prompt_yn("Do you want to import another gene list file?")){
            my $genelist3 = prompt("Give the name of the third genelist file:\n");
            print "genelist2 = \"$genelist3\"\n";
            open($genes3,'<',$genelist3) or die "Could not open file $genelist3 $!";
        }
    }
}

print "genes1 = \"$genes1\"\n";
print "genes2 = \"$genes2\"\n";
print "genes2 = \"$genes3\"\n";


my ($genelist1filter, $genelist1restfilter, $genelist2filter, $genelist2restfilter, $genelist3filter, $genelist3restfilter) ;

printf "At line %d\n", __LINE__;
print "genes1 is ", defined $genes1 ? "defined\n" : "not defined\n";

if (-e  $genes1 && -s $genes1){
    printf "At line %d\n", __LINE__;
    open($genelist1filter, '+>', "genelist1_missense_nonsense_frameshift_inframe_startloss_stoploss.txt") || die "Can't write new file: $!"; printf "At line %d\n", __LINE__;
    #first output file
    open($genelist1restfilter, '+>', "notingenelist_missense_nonsense_frameshift_inframe_startloss_stoploss.txt") || die "Can't write new file: $!"; #second output file
} # same for $genes2 and $genes3

printf "At line %d\n", __LINE__;


sub prompt {
    my ($query) = @_; # take a prompt string as argument
    local $| = 1; # activate autoflush to immediately show the prompt
    print $query;
    chomp(my $answer = <STDIN>);
    return $answer;
}


sub prompt_yn {
    my ($query) = @_;
    my $answer = prompt("$query (Y/N): ");
    return lc($answer) eq 'y';
}

另一次更新:

问题修订版中显示的输出显示了正在发生的事情。应用于-e的{​​{1}}和 - s工作正常。问题是当没有提供文件时,嘿被应用于$genes1$genes2。第33和34行的打印件显示在文本$genes3正上方的输出中,并确认未定义At line 51$genes2。它们由第23行和第27行中的$genes3调用分配值,否则它们将保留在第13和14行声明时获得的未定义值。

在文件测试open(...)中,值-e $genes1包含打开文件的句柄,因此测试有效。不需要第二个或第三个文件,因此不会对$genes1open执行$genes2,因此它们具有未定义的值。

测试应该改为:

$genes3

if ( defined $genes1 && -s $genes1){
if ( defined $genes2 && -s $genes2){

答案 1 :(得分:0)

考虑将-e和-s移动到单独的if块 - 检查文件是否存在于第一个块中,并在此块中添加文件大小检查。例如,

# check for existence
if (-e $genes1)
{
    # check size only if file exists
    if (-s $genes1)
    {
        # processing takes place here
    }
}