使用Perl打开文本文件并将其读入数组的最简单方法

20

给每个脚本都添加一个标准的Perl文件打开函数有点烦人:

sub openfile{
    (my $filename) = @_;
    open FILE,"$filename" or die $!;
    my @lines = <FILE>;
    return @lines;
}
我可以创建一个Perl模块来实现这个,但是这么简单的事情我相信已经有人做过了。
我正在尝试找到一种将文本文件读入数组的方法,但似乎没有Perl模块能够完成这个简单的任务...也许我在寻找时过于努力了,并且它可能已经随着标准5.10安装而自带了。
最理想的情况下,它应该看起来像这样:
my @lines = Module::File::Read("c:\some\folder\structure\file.txt");

我强烈推荐任何想要处理CSV文件的人使用Text::CSV::Slurp。这个模块比我尝试过的其他两三个模块都要好得多。其次最好的是CSV::Slurp::Simple或类似的模块,但不像Text::CSV::Slurp那样强大。 - Brian
2
使用open()的3个参数形式 http://p3rl.org/open - Brad Gilbert
8个回答

28

你有几个选项,经典的做法是:

my @array = do {
    open my $fh, "<", $filename
        or die "could not open $filename: $!";
    <$fh>;
};

IO::All方法: http://search.cpan.org/dist/IO-All/lib/IO/All.pod

use IO::All;

my @array = io($filename)->slurp;

这是 File::Slurp 方法:

use File::Slurp;

my @array = read_file($filename);

也许还有很多其他方法,毕竟存在“TIMTOWTDI”。


非常喜欢File::Slurp方法。非常感谢! - Brian
请注意,File::Slurp 早于 Perl IO 层,并且因此不会遵守 PERL_UNICODE/perl -C 设置,这可能会令你惊讶,特别是当你尝试编写具有适当的 Unicode 支持的 Perl 脚本时。Path::Tiny 可能是具有更好 Unicode 支持的替代方案。 - Martin von Wittich

16

那就是著名的“吞吐模式”:

  my @lines = <FILEHANDLE> ;

你还可以查看Perl Slurp Ease


1
“slurp mode” 更常用于将整个文件读入单个标量中,通过将记录分隔符 $/ 设置为 undef。 - ysth
我曾经看到过把数组和标量上下文都描述为 slurp模式的说法,但我更常见到使用数组的方式。 - codehearted

15

7

请查看Perl6::Slurp,该软件实现了Perl6版本的slurp,并被推荐在《Perl最佳实践》一书中使用。

以下是一些示例...

my @lines         = slurp 'filename';
my @lines_chomped = slurp 'filename', { chomp => 1 };
my @lines_utf8    = slurp 'filename', { utf8  => 1 };

6

如果你要读取较大的文件,且不希望将整个文件读入内存中,则可以考虑使用Tie::File模块。这是一个核心模块。此外,请参阅perlfaq5


4
你已经掌握了一般的技巧,但我想提醒你Perl不太鼓励这样做,因为很多时候你可以一行代码实现同样的功能,这样更加高效。

一个好的观点,尤其是在读入数组时。数组意味着按行(如果使用 $/ 则意味着按记录)顺序处理,通常最好逐个处理。然而,有些情况下 slurp 也是适当的。 - Chas. Owens

2

如果需要快速简便的方式,我更喜欢直接操作 @ARGV 的简单性。

# Ysth is right, it doesn't automatically die; I need another line.
use 5.010;
use strict;
my @rows = do { 
    use warnings FATAL => 'inplace'; # oddly enough, this is the one. ??
    @ARGV='/a/file/somewhere';
    <>;
};
say q(Not gettin' here.);

如果perl无法打开文件,它会自动失败。


* - 可执行文件,请勿大写。


1
我不知道Perl不是一个缩写词!谢谢你提醒我。 - Brian
1
抱歉,这个注释不是给你的,而是针对臭名昭著的大写字母P帮派的。他们会闯入你的帖子并将你特别指定为可执行文件的P大写化。该语言只有一个大写字母P。虽然没有变位词。 - Axeman
我认为大写字母P的团队很注意区分。 - ysth
不,Perl不会自动终止程序 - 它只是发出警告并继续执行。 - ysth

2
我建议采用面向对象的方法,不需要使用核心分发之外的模块,并且可以在任何地方运行:
use strict;
use warnings;
use IO::File;
my $fh = IO::File->new("< $file");

foreach ($fh->getlines) {
    do_something($_);
}
$fh->close

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接