はい、 それを行うには複数の方法があります ですが、標準的な方法、最も効率的な方法、または最も簡潔な方法が必要です。私が知っている回答を追加し、何がトップに浸透するかを確認します。
明確にするために、問題は、ファイルの内容を文字列に読み込む方法が最適であることです。回答ごとに1つのソリューション。
これはどう:
use File::Slurp;
my $text = read_file($filename);
ETA:注 ファイルスラップのバグ#83126:エンコーディングによるセキュリティホール(UTF-8) 。 File :: Slurper (免責事項:私が作成したもの)を使用することをお勧めします。これは、エンコーディングに関するデフォルトの方が優れているためです。
use File::Slurper 'read_text';
my $text = read_text($filename);
または Path :: Tiny :
use Path::Tiny;
path($filename)->Slurp_utf8;
@ARGV
をローカライズするdo
ブロックでこれを行うのが好きなので、ひし形演算子を使用してファイルマジックを実行できます。
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は多くのスラッピング方法で多くの研究を行いました。彼は ここでの彼の発見 を書き留め、それらに情報File :: 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>
};
私は実際に魔法<>を使用する場合を除いて、魔法<>の大ファンではありません。それを偽装する代わりに、なぜオープンコールを直接使用しないのですか?これはそれほど多くの作業ではなく、明示的です。 (特に「-」を処理する場合の真の魔法<>は、完全にエミュレートするための作業がはるかに多くなりますが、ここではそれを使用していません。)
文字列のmmap(メモリマッピング)は、次の場合に役立ちます。
#!/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);
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;
これは高速でも、プラットフォームに依存せず、実際に悪でもありませんが、短いです(そして、私はラリー・ウォールのコードでこれを見てきました;-):
my $contents = `cat $file`;
子供たちは、家でそれをしないでください;-)。
Perl6 :: Slurp の概要を参照してください。これは信じられないほど柔軟であり、一般的にほとんど労力を費やすことなく正しいことを行います。
誰もreadやsysreadについて何も言わなかったので、ここにシンプルで速い方法があります:
my $string;
{
open my $fh, '<', $file or die "Can't open $file: $!";
read $fh, $string, -s $file; # or sysread
close $fh;
}
ワンライナーの場合、通常は the -0
スイッチ (-n
)Perlがファイル全体を一度に読み取るようにします(ファイルにnullバイトが含まれていない場合):
Perl -n0e 'print "content is in $_\n"' filename
バイナリファイルの場合は、-0777
:
Perl -n0777e 'print length' filename
以下に、最も一般的な方法の比較を示します。
http://poundcomment.wordpress.com/2009/08/02/Perl-read-entire-file/
それを行うための最悪の方法の候補! (コメントを参照してください。)
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;