如何以递归方式打开在另一个文件中找到的名称的文件

问题描述 投票:-1回答:1

递归打开文件而不会破坏perl中的文件句柄

#!usr/bin/perl
   $set=1; 
   open (MYFILE, 'file1.txt'); 
   $array[$set]=\*MYFILE; 
   printit ($array[$set]); 

   sub printit {    
     ($array[$set])=shift;    
     $fh=<$array[$set]>;
     while (<$fh>) {
       chomp($fh); 
       #print data in the file
       if($fh=~/\.txt/){
           #print $fh;
           open (files,"$fh");
           $set=$set+1;
           printit(*files);
           $set=$set-1;
          }
    } 
}   
file1.txt -file2.txt,file3.txt#假定file2.txt在file3.txt之前file2.txt-file4.txt file3.txt

我想打开file1.txt并在file1中打印数据,如果我发现文件中的file2.txt打开文件以打印数据并递归直到文件中不包含.txt文件,然后返回(横断树)在我们的情况下file1-> file2-> file4-> file3-> file1结尾程序。我不知道为什么我的程序无法正常工作。预先感谢*

file perl recursion filehandle
1个回答
2
投票

我的问题:读取文件,如果找到文件名(由.txt判断),则打开并读取文件名,然后递归进行。发布的代码存在一些基本错误,如下所述。

我假设首先需要打印文件的所有行,然后进入下一个文件(如果找到)。下面的代码允许关闭文件句柄;它的微小变化使它们保持排列并打开。

use warnings;
use strict;
use feature 'say';

my $file = shift @ARGV || 'file.txt';

open my $fh, '<', $file or die "Can't open $file: $!";

recurse_open($fh);

sub recurse_open {
    my ($fh) = shift;
    my @files;
    while (<$fh>) {
        print;
        if (/\b(.+?\.txt)\b/) {
            push @files, $1; 
        }   
    }   
    say '---';
    foreach my $file (@files) {
        open my $fh_next, '<', $file  or do {
            warn "Can't open $file: $!";
            next;
        };
        recurse_open($fh_next);
    }   
}

此打印

主文件文件1.txt在其中主文件末尾---提交一个一行与file2.txt一个结束---文件二,其中有一行与file3.txt两个结束---只是文件3,没有更多的文件名。---

希望file.txt和文件1..3的内容清晰可见(用---分隔)。如果碰巧有多个文件名,则对文件中存在的所有文件名进行跟进。

如果标题中的短语“ 不破坏文件句柄”表示文件句柄应保持打开状态(并收集),则只需在打开时将它们添加到数组中即可

open my $fh, '<', $file or die "Can't open $file: $!";
my @filehandles = ($fh);

recurse_open($fh, \@filehandles);

sub recurse_open {
    my ($fh, $handles) = @_;
    ...
    foreach my $file (@files) {
        open my $fh_next, '<', $file  or do {
            warn "Can't open $file: $!";
            next;
        };    
        push @$handles, $fh_next;
        recurse_open($fh_next, $handles);
    }
}

通常,(词法)文件句柄超出范围时将关闭它。但是,由于现在将每个副本都复制到更大范围内定义的数组中,因此将它们保留下来,因为每个版本都有一个引用。


对问题代码的评论。

最严重的错误是对文件句柄的含义和作用的明显误解。表达式<$fh>从打开时与文件句柄$fh关联的文件中读取,其中<>readline的运算符版本。参见I/O Operators in perlop

这将在文件中返回一行,并且that是您应该使用的内容,使用chompm//等,而不是$fh本身。使用while (<$fh>)(条件中没有其他内容),将行分配给special variable $_,这在Perl中是默认设置。上面的代码利用了这一点。

接下来,您实际上并不匹配并捕获文件名,而仅匹配.txt。 (该匹配使用文件句柄而不是包含该行的变量,并且open使用该文件句柄代替文件名,这是上面提到的文件句柄混淆。)

然后,我看不到在$set周围增加和减少该舞蹈的必要性。由于您很好地将所有这些操作都放到了子例程中,因此只需在变量中使用filehandle即可。所以我取消了阵列。如果出于某些其他原因需要将其还原。

最后:

  • Alwaysuse warnings;use strict;启动程序。这不是什么学问,但是direct帮助发现错误,并且也执行了一些非常好的做法。

  • 总是检查您的open通话(open ... or ...

  • 使用词法文件句柄(my $fh)代替glob(FH),它们要好得多。使用open

  • 的三参数版本

如果这是全部目的,则最好将文件名传递给递归子文件,并使其打开并读取文件。

© www.soinside.com 2019 - 2024. All rights reserved.