Perl Language
De inhoud van een bestand in een variabele lezen
Zoeken…
De handmatige manier
open my $fh, '<', $filename
or die "Could not open $filename for reading: $!";
my $contents = do { local $/; <$fh> };
Na het openen van het bestand (lees man perlio
als je specifieke bestandscoderingen wilt lezen in plaats van onbewerkte bytes), zit de truc in het do
blok: <$fh>
, de bestandsingang in een diamantoperator, retourneert een enkel record uit het bestand . De "input record separator" variabele $/
specificeert wat een "record" is - standaard staat deze op een nieuweteken, dus "een record" betekent "een enkele regel". Omdat $/
een globale variabele is, doet local
twee dingen: het maakt een tijdelijke lokale kopie van $/
die aan het einde van het blok verdwijnt en geeft het de (niet-) waarde undef
(de "waarde" die Perl geeft naar niet-geïnitialiseerde variabelen). Wanneer het invoerrecordscheidingsteken die (niet-) waarde heeft, retourneert de diamantoperator het volledige bestand. (Het beschouwt het hele bestand als één regel.)
Met do
kunt u zelfs handmatig een bestand openen. Voor het herhaaldelijk lezen van bestanden,
sub readfile { do { local(@ARGV,$/) = $_[0]; <> } }
my $content = readfile($filename);
kan worden gebruikt. Hier wordt een andere globale variabele ( @ARGV
) gelokaliseerd om hetzelfde proces te simuleren dat wordt gebruikt bij het starten van een perl-script met parameters. $/
is nog steeds niet undef
, omdat de array ervoor alle inkomende argumenten "opeet". Vervolgens levert de diamantoperator <>
opnieuw één record gedefinieerd door $/
(het hele bestand) en keert terug van het do
blok, dat op zijn beurt terugkeert van de sub.
De sub heeft geen expliciete foutafhandeling, wat een slechte gewoonte is! Als er een fout optreedt tijdens het lezen van het bestand, ontvangt u undef
als retourwaarde, in tegenstelling tot een lege tekenreeks uit een leeg bestand.
Een ander nadeel van de laatste code is het feit dat u PerlIO niet kunt gebruiken voor verschillende bestandscoderingen - u krijgt altijd onbewerkte bytes.
Path :: Tiny
Het idioom van The Manual Way meerdere keren gebruiken in een script wordt al snel vervelend, dus misschien wilt u een module proberen.
use Path::Tiny;
my $contents = path($filename)->slurp;
U kunt een binmode
optie doorgeven als u controle nodig hebt over bestandscoderingen, regeleinden, enz. - zie man perlio
:
my $contents = path($filename)->slurp( {binmode => ":encoding(UTF-8)"} );
Path::Tiny
ook veel andere functies voor het omgaan met bestanden, dus het kan een goede keuze zijn.
File :: Slurper
Dit is een minimalistische module die bestanden alleen in variabelen slurpt, niets anders.
use File::Slurper 'read_text';
my $contents = read_text($filename);
read_text()
neemt twee optionele parameters om de bestandscodering op te geven en of regeleinden moeten worden vertaald tussen de Unixish LF of DOSish CRLF-standaarden:
my $contents = read_text($filename, 'UTF-8', 1);
File :: Slurp
Gebruik het niet. Hoewel het al lang bestaat en nog steeds de module is die de meeste programmeurs zullen voorstellen, is het stuk en zal het waarschijnlijk niet worden opgelost .
Een bestand slurpen tot een matrixvariabele
open(my $fh, '<', "/some/path") or die $!;
my @ary = <$fh>;
Wanneer geëvalueerd in lijstcontext, retourneert de diamantoperator een lijst die bestaat uit alle regels in het bestand (in dit geval het resultaat toewijzen aan een contextcontext van een arraylevering). De lijnafsluiter blijft behouden en kan worden verwijderd door chomping:
chomp(@ary); #removes line terminators from all the array elements.
Slurp-bestand in één voering
Input record separator kan worden gespecificeerd met -0
schakelaar ( nul , geen hoofdletter O ). Het heeft een octaal of hexadecimaal getal als waarde. Elke waarde 0400
of hoger zorgt ervoor dat Perl bestanden slurpt, maar volgens afspraak is de waarde die voor dit doel wordt gebruikt 0777
.
perl -0777 -e 'my $file = <>; print length($file)' input.txt
Om verder te gaan met minimalisme, geeft het opgeven van de schakelaar -n
dat Perl automatisch elke regel (in ons geval het hele bestand) in variabele $_
leest.
perl -0777 -ne 'print length($_)' input.txt