如何修改这个 Perl 子例程,以便它使用 print_file 打印文件的内容?

Posted

技术标签:

【中文标题】如何修改这个 Perl 子例程,以便它使用 print_file 打印文件的内容?【英文标题】:How can I modify this Perl subroutine so that it prints the contents of the file, using print_file? 【发布时间】:2022-01-01 08:04:54 【问题描述】:

阅读 Allen B. Downey 的 Learning Perl the Hard Way

练习 1.1 说:

glob 运算符将模式作为参数并返回一个列表 匹配给定模式的所有文件。 glob 的一个常见用途是列出文件 在目录中。

my @files = glob "$dir/*";

$dir/* 模式表示“目录中名称存储在$dir 中的所有文件”。 有关其他模式的示例,请参阅 glob 的文档。 编写一个名为 print dir 的子程序,它将目录的名称作为参数 并打印该目录中的文件,每行一个。

我做到了:

#!/usr/bin/perl

sub print_dir 

        my $dir = shift;

        my @files = glob "$dir/*";

        foreach my $file (@files) 

                print "$file\n";
        



print_dir @ARGV;

然后练习 1.2 说“修改前面的子程序,而不是打印名称 文件,它使用 print_file 打印文件的内容。'

我正在努力解决这个问题。我有一个打印文件内容的脚本:

#!/usr/bin/perl

use strict;
use warnings;

sub print_file 
        my $file = shift;
        open(my $FILE, $file) 
             or die $!;
        while (my $line = <$FILE>) 
                print $line;
        


sub cat 
        foreach my $file (@_) 
                print_file $file;
        


cat @ARGV;

然后我有上面的另一个脚本,它打印目录中所有文件的名称。所以这就是我到目前为止尝试获取目录中的所有文件然后打印所有这些文件的内容:

#!/usr/bin/perl

use strict;
use warnings;

sub print_file 
        my $file = shift;
        open(my $FILE, $file)
             or die $!;
        while (my $line = <$FILE>) 
                print $line;
        


sub print_dir 
        my $dir = shift;
        my @files = glob "$dir/*";

        while (my $dir = shift)   
                foreach my $file (@files) 
                        print_file "$file";
                
        


print_dir @ARGV;

显然它不起作用,也没有错误消息。

【问题讨论】:

您无缘无故地在文件名中添加了换行符。 "$file\n" 应该是 $file 注意:为了代码的完整性,如果文件是打开的,一旦使用了文件处理程序就应该关闭(perl 会为你做这件事,尽管对于干净的代码,文件句柄还是应该关闭)。 注意:在最后一个代码示例中while (my $dir = shift) 可能会返回您不打算接收的内容(您已经在进入子程序时转移了参数)。 注意:如果你打算print $var . "\n",那么 perl 提供了一个替代的say $var 来简化代码的可读性。 【参考方案1】:

您无缘无故地在文件名中添加了换行符。

print_file "$file\n";

应该是

print_file $file;

顺便说一句,无用使用全局变量(如FILE)是一种不好的做法。最好检查 open 是否有错误,因为它很容易出现错误。

open my $FILE, $file
   or die "Can't open \"$file\": $!\n";

while (my $line = <$FILE>) 
   ...

有了你的错误,这会输出类似

Can't open "./some_file
": No such file or directory

【讨论】:

【参考方案2】:

以下代码 sn-ps 为您的练习演示了两种可能的解决方案。

Perl 代码可以非常简洁地表达所需的算法(原理: 简洁是智慧的灵魂)。

注意 1:代码验证传递的参数是一个目录

注2:代码跳过目录内容的输出,因为它不是文件

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

print_dir($_) for @ARGV;

sub print_dir 
    my $dir = shift;
    
    die "$dir isn't a directory" unless -d $dir;
    
    say for glob("$dir/*");

修改代码以打印文件内容

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

print_dir($_) for @ARGV;

sub print_dir 
    my $dir = shift;

    die "$dir isn't a directory" unless -d $dir;
    
    for my $fname ( glob("$dir/*") ) 
        next if -d $fname;             # skip directories
        say "\n" . '-' x 25 
          . "\n" . $fname 
          . "\n" . '-' x 25;
        open my $fh, '<', $fname
            or die "Couldn't open $fname";
        print while <$fh>;
        close $fh;
    

参考:

-X file test glob open die say perlvar 教程:Perl file test operators 教程:Perl special variables

推荐:

Learn Perl Perl Documentation Perl Library Free Perl Books

【讨论】:

以上是关于如何修改这个 Perl 子例程,以便它使用 print_file 打印文件的内容?的主要内容,如果未能解决你的问题,请参考以下文章

如何使用 Doxygen 和 Doxygen::Filter::Perl 为 Perl 子例程生成文档?

如何在 Perl 子例程中处理已捕获和未捕获的错误?

如何在远程主机上调用 perl 子例程(可能通过系统命令)?

什么时候应该使用 & 来调用 Perl 子例程?

如何在Perl子例程中使用$ a和$ b

调用 perl 子例程