【问题标题】:Returning arrays in Perl在 Perl 中返回数组
【发布时间】:2023-04-05 13:45:02
【问题描述】:

我正在研究 Perl 中的递归文件查找函数,它应该返回一个文件名数组。但是,当我尝试打印它们时,会发生什么,我只是得到0。我做错了什么?

use strict;
use File::Basename;
use constant debug => 0;

sub isdir {
    return (-d $_[0]);
}

sub isfile {
    return (-f $_[0]);
}

my $level = 0;

#my @fns = ();

sub getfn {
    my @fns = ();
    my($file, $path) = @_;
    my (undef, undef, $ext) = fileparse($file, qr"\.[^.]+$");
    $level++;
    print "-->>getfn($level): $file : $path\n" if debug;
    print "arg:\t$file\t$path ($ext)\n" if debug;
    if ($ext eq ".bragi") {
        open my $FILE, "<", "$path/$file" or die "Failed to open $path/$file: $!";
        my @lines = <$FILE>;
        close $FILE;
        foreach my $line (@lines) {
            chomp($line);
            my $fullpath = "$path/$line";
            print "---- $fullpath\n" if debug;
            if (isfile($fullpath)) {
                #print "file:\t$fullpath\n";
                push(@fns, $fullpath);
                getfn($line, $path);
            }
            elsif (isdir($fullpath)) {
                #print "DIR:\t$fullpath\n";
                opendir my ($dh), $fullpath or
                    die "$fullpath does not exist or is not a directory: $!";
                my @files = readdir $dh;
                closedir $dh;
                foreach my $f (@files) {
                    getfn($f, "$fullpath");
                }
            }
        }
    }
    print "<<--getfn($level)\n" if debug;
    $level--;
    #print @fns;
    return @fns;
}


foreach my $f (<*>) {
    #print "fn: ".$f."\n";
    my (undef, undef, $ext) = fileparse($f, qr"\.[^.]+$");
    if ($ext eq ".bragi") {
    print &getfn($f, $ENV{PWD})."\n";
    }
}

【问题讨论】:

  • 你看过 File::Find::Closures 吗?你可能不需要做任何工作,或者通过窃取代码来做很少的工作。 :)

标签: arrays perl function return subroutine


【解决方案1】:

这里的主要问题是这样的一行:

getfn($line, $path);

并没有真正做任何事情。它会在子目录中找到所有文件,但随后会完全丢弃它们。您需要将其返回值合并到外部调用的@fns

第二个问题是:

print &getfn($f, $ENV{PWD})."\n";

强制将返回的数组视为标量,因此它打印数组元素的number,而不是数组元素的contents。你可能想要这样的东西:

print "$_\n" foreach getfn($f, $ENV{PWD});

【讨论】:

  • print &amp;getfn($f, $ENV{PWD}),"\n"; 也许。连接将导致标量上下文,逗号将保留列表上下文。不错的收获。
  • 有什么理由将&amp; 添加到子例程调用的前面吗?据我了解,Perl 5 中很少需要这样做,但也许这是我遗漏的一个不起眼的案例。
  • @davorg:我没有。我的答案中唯一的&amp; 是我正在评论的代码,我从问题中复制了该代码。 (也就是说,如果我正在编写这个程序,我可能会将getfn 定义为sub getfn($$) { ...,然后我只会在递归调用中包含&amp;,只是为了绕过有关未检查原型的警告。)
【解决方案2】:

当您递归调用getfn() 时,您永远不会将返回的数组分配给任何东西。你唯一的任务是:

my @fns = ();

在函数的顶部,这就是返回的内容。

【讨论】:

  • 我不能打印而不是分配吗?
  • 等一下,我将元素推送到它
  • 这是错误的。 print @array 将打印数组的所有元素,由 $, 设置的任何值分隔(默认为“”)。例如。 “foobarbaz”。它不会打印数组中的项目数,除非您使用print scalar @array 或类似技术来施加标量上下文。 ruakh 发现了这一点,与 . 的连接确实会施加标量上下文,这是您的错误。
  • 是的,我的 perl 生锈了,忘记了 concat 导致标量打印。
猜你喜欢
  • 2018-03-24
  • 2012-06-28
  • 1970-01-01
  • 1970-01-01
  • 2011-03-21
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2015-12-04
相关资源
最近更新 更多