是的,有不止一种方法可以做到这一点,但必须有一种规范的或最有效或最简洁的方法。我会添加我知道的答案,看看哪些内容会渗透到顶部。
需要明确的是,问题是如何最好地将文件的内容读取到字符串中。 每个答案一个解决方案。
这个怎么样:
use File::Slurp;
my $text = read_file($filename);
预计到达时间:注意 File-Slurp 的 Bug #83126:编码 (UTF-8) 的安全漏洞。我现在推荐使用 File::Slurper (免责声明:我写的),也是因为它在编码方面有更好的默认值:
use File::Slurper 'read_text';
my $text = read_text($filename);
或
路径::微小:
use Path::Tiny;
path($filename)->slurp_utf8;
do
块来执行此操作,在其中定位
@ARGV
,这样我就可以使用菱形运算符来为我执行文件魔法。
my $contents = do { local(@ARGV, $/) = $file; <> };
如果您需要更强大一点,您可以轻松地将其变成子例程。
如果您需要真正强大的东西来处理各种特殊情况,请使用File::Slurp。即使您不打算使用它,也请查看源代码以了解它必须处理的所有古怪情况。 File::Slurp 有一个大的安全问题,但看起来并没有解决方案。部分原因是它无法正确处理编码。即使我的快速回答也有这个问题。如果您需要处理编码(可能是因为默认情况下您没有将所有内容都设置为 UTF-8),则这会扩展为:
my $contents = do {
open my $fh, '<:encoding(UTF-8)', $file or die '...';
local $/;
<$fh>;
};
如果您不需要更改文件,您也许可以使用
File::Map。
File::Slurp(这是最好的方式)时,Uri Guttman 对多种 slurp 方式以及哪种方式最有效进行了大量研究。他在这里写下他的发现并将其纳入信息文件::Slurp。
open(my $f, '<', $filename) or die "OPENING $filename: $!\n";
$string = do { local($/); <$f> };
close($f);
my $contents = do {
local $/;
open my $fh, $filename or die "Can't open $filename: $!";
<$fh>
};
我不太喜欢魔法<>,除非实际使用魔法<>。与其伪造它,为什么不直接使用 open call 呢?这并不需要太多工作,而且很明确。 (真正的魔法 <>,特别是在处理“-”时,要完美模拟需要做更多的工作,但我们无论如何都不会在这里使用它。)
#!/usr/bin/perl
use warnings; use strict;
use IO::File;
use Sys::Mmap;
sub sip {
my $file_name = shift;
my $fh;
open ($fh, '+<', $file_name)
or die "Unable to open $file_name: $!";
my $str;
mmap($str, 0, PROT_READ|PROT_WRITE, MAP_SHARED, $fh)
or die "mmap failed: $!";
return $str;
}
my $str = sip('/tmp/words');
print substr($str, 100,20);
更新:2012 年 5 月
将Sys::Mmap 替换为 File::Map 后,以下内容应该非常等效
#!/usr/bin/perl
use warnings; use strict;
use File::Map qw{map_file};
map_file(my $str => '/tmp/words', '+<');
print substr($str, 100, 20);
my $contents = `cat $file`;
孩子们,不要在家里这样做;-)。
use Path::Class;
file('/some/path')->slurp;
{
open F, $filename or die "Can't read $filename: $!";
local $/; # enable slurp mode, locally.
$file = <F>;
close F;
}
use IO::All;
# read into a string (scalar context)
$contents = io($filename)->slurp;
# read all lines an array (array context)
@lines = io($filename)->slurp;
Perl6::Slurp 的摘要,它非常灵活,通常只需很少的努力就能做正确的事情。
my $string;
{
open my $fh, '<', $file or die "Can't open $file: $!";
read $fh, $string, -s $file; # or sysread
close $fh;
}
open(F, $filename) or die "OPENING $filename: $!\n";
@lines = <F>;
close(F);
$string = join('', @lines);
$/
undef $/;
open FH, '<', $filename or die "$!\n";
my $contents = <FH>;
close FH;
open(IN, "<$filename");
$contents = join('', <IN>);
close(IN);
详情:
<IN>
是一个文件描述符,如果分配给列表变量/上下文,则返回行列表(也称为数组)。
join
采用分隔符和行列表,并返回所有行连接在一起的字符串。来源:https://perldoc.perl.org/functions/join)。
open
,文件名前缀为“<" opens the file in read-mode.我经常使用 join 结构来表达单行,例如
perl -e '$_=join("",<>);s/multiline_regex/replacement_string/gms;print'
。 m/s 选项支持多行正则表达式,请参阅https://perldoc.perl.org/perlre。