Perl Language
Läsa en fils innehåll i en variabel
Sök…
Det manuella sättet
open my $fh, '<', $filename
or die "Could not open $filename for reading: $!";
my $contents = do { local $/; <$fh> };
Efter att ha öppnat filen (läs man perlio
om du vill läsa specifika filkodningar istället för råbyte), är tricket i do
blocket: <$fh>
, filhandtaget i en diamantoperatör, returnerar en enda post från filen . Variabeln "input record separator" $/
specificerar vad en "record" är - som standard är den inställd på en ny linje-karaktär så "en record" betyder "en enda rad". Eftersom $/
är en global variabel, gör local
två saker: det skapar en tillfällig lokal kopia av $/
som kommer att försvinna i slutet av blocket och ger det (icke-) värdet undef
(det "värde" som Perl ger till oinitialiserade variabler). När ingångsregistreringsavskiljaren har det (icke-) värdet kommer diamantoperatören att returnera hela filen. (Den anser att hela filen är en enda rad.)
Med do
kan du till och med komma runt manuellt att öppna en fil. För upprepad läsning av filer,
sub readfile { do { local(@ARGV,$/) = $_[0]; <> } }
my $content = readfile($filename);
kan användas. Här är en annan global variabel ( @ARGV
) lokaliserad för att simulera samma process som används när man startar ett perl-skript med parametrar. $/
är fortfarande undef
, eftersom matrisen framför den "äter" alla inkommande argument. Därefter levererar diamantoperatören <>
igen en post definierad av $/
(hela filen) och återgår från do
blocket, som i sin tur återvänder från suben.
Subben har ingen uttrycklig felhantering, vilket är dålig praxis! Om ett fel uppstår när du läser filen får du undef
som returvärde, i motsats till en tom sträng från en tom fil.
En annan nackdel med den sista koden är det faktum att du inte kan använda PerlIO för olika filkodningar - du får alltid råbyte.
Path :: Tiny
Att använda formspråket från The Manual Way flera gånger i ett skript blir snart tråkigt så du kanske vill prova en modul.
use Path::Tiny;
my $contents = path($filename)->slurp;
Du kan passera ett binmode
alternativ om du behöver kontroll över filkodningar, radavslut etc. - se man perlio
:
my $contents = path($filename)->slurp( {binmode => ":encoding(UTF-8)"} );
Path::Tiny
har också många andra funktioner för att hantera filer så det kan vara ett bra val.
File :: Slurper
Detta är en minimalistisk modul som bara slurper filer till variabler, inget annat.
use File::Slurper 'read_text';
my $contents = read_text($filename);
read_text()
tar två valfria parametrar för att ange filkodningen och om radändelser ska översättas mellan unixish LF- eller DOSish CRLF-standarder:
my $contents = read_text($filename, 'UTF-8', 1);
File :: Slurp
Använd inte det. Även om det har funnits länge och fortfarande är den modul som de flesta programmerare kommer att föreslå är den trasig och troligen inte fixad .
Slurping en fil till en matrisvariabel
open(my $fh, '<', "/some/path") or die $!;
my @ary = <$fh>;
Vid utvärdering i listkontext returnerar diamantoperatören en lista som består av alla raderna i filen (i detta fall tilldelar du resultatet till en matrisförrådslista-kontext). Linjeterminatorn hålls kvar och kan tas bort genom chomping:
chomp(@ary); #removes line terminators from all the array elements.
Slurp-fil i enfodral
Inmatningsregistreringsavskiljare kan specificeras med -0
omkopplaren ( noll , inte kapital O ). Det tar ett oktalt eller hexadecimalt värde som värde. Varje värde 0400
eller 0400
kommer att göra att Perl slurper filer, men enligt konventionen är värdet som används för detta ändamål 0777
.
perl -0777 -e 'my $file = <>; print length($file)' input.txt
Att gå vidare med minimalism och att specificera -n
switch gör att Perl automatiskt läser varje rad (i vårt fall - hela filen) till variabel $_
.
perl -0777 -ne 'print length($_)' input.txt