在连接(。)或字符串问题中使用未初始化的值

时间:2014-11-17 15:24:29

标签: perl

我知道在执行Perl脚本时这是一个非常常见的问题,但我找不到解决方案,可能它非常简单。

我的数据文件夹中有两个文件夹:BWA_1和BWA_2。我想用这个文件夹中的某个文件的完整路径打印文件名。要做到这一点,我在脚本中有这些行。

my $rpath="/home/seq4/Desktop/data/";

for ( my $i = 1; $i <= 2; $i++ ) {
    my $BWA_dir = $rpath . "BWA_" . $i;
    print "$BWA_dir\n";
    my $bam_file = glob("$BWA_dir/*SNP.bam");
    print "$bam_file\n";
}

执行时:

/home/seq4/Desktop/data/BWA_1
/home/seq4/Desktop/data/BWA_1/subset_fusa.SNP.bam
/home/seq4/Desktop/data/
Use of uninitialized value $bam_file in concatenation (.) or string at sc.pl line 17.

如何解决此问题?

该文件存在。如果我改变这一行:

my $bam_file = glob("$BWA_dir/*SNP.bam");

使用此(两个文件具有相同的名称):

my $bam_file = $BWA_dir . "/subset_fusa.SNP.bam";

输出:

    /home/seq4/Desktop/data/BWA_1
    /home/seq4/Desktop/data/BWA_1/subset_fusa.SNP.bam
    /home/seq4/Desktop/data/BWA_2
    /home/seq4/Desktop/data/BWA_2/subset_fusa.SNP.bam

文件存在......:

ls -la BWA_2/
total 8
drwxrwxr-x 2 seq4 alg89 4096 nov 17 17:16 .
drwxrwxr-x 4 seq4 alg89 4096 nov 17 17:15 ..
-rw-rw-r-- 1 seq4 alg89    0 nov 17 17:16 subset_fusa.SNP.bam

2 个答案:

答案 0 :(得分:2)

文档perldoc -f glob中描述了这一点:

glob EXPR
glob    In list context, returns a (possibly empty) list of filename
        expansions on the value of EXPR such as the standard Unix shell
        /bin/csh would do. In scalar context, glob iterates through such
        filename expansions, returning undef when the list is exhausted.

请注意,您在标量上下文中使用glob,在我看来,这是使用它的错误方法。如果有多个匹配的文件,您将只获得第一个。这样做的自然方法是使用带有for循环的列表上下文:

for my $file (glob ...) {
    print "$file\n";
}

使用标量上下文使用while循环进行迭代:

while (my $file = glob ...) {

另请注意,您可以使用glob来完成整个事情:

my @files = glob "data/BWA_{1,2,3}/*SNP.bam";

(您可以简单地使用BWA_*。)

修改

我发现了你的代码不起作用的真正原因。我在我的系统上尝试了它并且我得到了相同的行为,即使文件清楚存在。

你没有得到预期结果的原因就像我早期所说的那样你在标量上下文中使用glob。它迭代结果,在第一个之后,它返回undef。您更改了glob中使用的变量并不重要。通过更改代码中的2个字符,我得到了所需的结果:

my $rpath = "foo/";

for ( my $i = 1; $i <= 2; $i++ ) {
    my $BWA_dir = $rpath . "BWA_" . $i;
    print "$BWA_dir\n";
    my @bam_file = glob("$BWA_dir/*SNP.bam");
    #  ^--- changed to array to impose list context
    print "@bam_file\n";
}

有人可能会认为使用新字符串再次使用该语句会刷新迭代器,但事实并非如此。这可能是一些优化。

答案 1 :(得分:1)

您收到此警告是因为$bam_file未定义,因为没有文件匹配/home/Desktop/data/BWA_2/*SNP.bam,或者您无权首先读取该文件夹。如果您希望阻止该警告,您可以做一些事情:

根据是否找到文件更改字符串:

my $bam_file = glob("$BWA_dir/*SNP.bam") || ''; # If glob returns undef, make $bam_file an empty string

仅在找到文件时打印:

print "$bam_file\n" if (defined $bam_file);