Dateien lesen und schreiben
Moderne Perl-Skripte nutzen die Dreiargument-Form von open mit lexikalischem Dateihandle und prüfen immer auf Fehler:
use strict; use warnings;
use File::Temp qw(tempdir);
my $dir = tempdir(CLEANUP => 1);
my $pfad = "$dir/demo.txt";
open(my $out, '>', $pfad) or die "Kann $pfad nicht schreiben: $!";
print $out "Zeile 1\n";
printf $out "%s hat %d Punkte\n", "Mia", 120;
print {$out} "Zeile 3\n";
close($out);
open(my $anh, '>>', $pfad) or die $!; # anhängen
print $anh "Zeile 4\n";
close $anh;
open(my $in, '<', $pfad) or die "Kann nicht lesen: $!";
while (my $zeile = <$in>) {
chomp $zeile;
print "$.: $zeile\n"; # $. = Zeilennummer
}
close $in;
open($in, '<', $pfad) or die;
my @alle = <$in>; # alle Zeilen auf einmal
close $in;
print "Zeilen: ", scalar(@alle), "\n";
open($in, '<', $pfad) or die;
my $inhalt = do { local $/; <$in> }; # komplette Datei als ein String
close $in;
print "Länge: ", length($inhalt), "\n";
if (open(my $fehler, '<', "$dir/gibt-es-nicht")) { close $fehler }
else { print "Fehler: ", $! =~ s/ at.*//r, "\n"; }Ausgabe
1: Zeile 1 2: Mia hat 120 Punkte 3: Zeile 3 4: Zeile 4 Zeilen: 4 Länge: 43 Fehler: No such file or directory
| Modus | Bedeutung |
|---|---|
< | lesen |
> | schreiben (überschreibt) |
>> | anhängen |
+< | lesen und schreiben |
Für Text mit Umlauten: open(my $fh, '<:encoding(UTF-8)', $pfad).
Dateitests und Verzeichnisse
use strict; use warnings;
use File::Temp qw(tempdir);
use File::Spec;
use File::Basename qw(basename dirname fileparse);
my $dir = tempdir(CLEANUP => 1);
mkdir "$dir/unter" or die;
for my $n (qw(a.txt b.txt c.log)) {
open(my $f, '>', "$dir/$n") or die; print $f "x" x 10; close $f;
}
print "Datei\n" if -f "$dir/a.txt";
print "Ordner\n" if -d "$dir/unter";
print "Größe: ", -s "$dir/a.txt", "\n";
print "nicht vorhanden\n" unless -e "$dir/nix";
print "lesbar\n" if -r "$dir/a.txt";
my @txt = sort map { basename($_) } glob("$dir/*.txt");
print "@txt\n";
opendir(my $dh, $dir) or die;
my @eintraege = sort grep { !/^\./ } readdir($dh);
closedir $dh;
print "@eintraege\n";
print basename("/a/b/c.txt"), " ", dirname("/a/b/c.txt"), "\n";
my ($name, $pfad, $endung) = fileparse("/a/b/bericht.txt", qr/\.[^.]*/);
print "$name | $endung\n";
print File::Spec->catfile("a", "b", "c.txt"), "\n";
rename "$dir/a.txt", "$dir/z.txt" or die;
unlink "$dir/z.txt";
print "gelöscht\n" unless -e "$dir/z.txt";Ausgabe
Datei Ordner Größe: 10 nicht vorhanden lesbar a.txt b.txt a.txt b.txt c.log unter c.txt /a/b bericht | .txt a/b/c.txt gelöscht
Kommandozeile, Umgebung, Programme
use strict; use warnings;
@ARGV = ("datei.txt", "--verbose"); # normalerweise vom Aufruf gefüllt
print "Argumente: @ARGV (", scalar(@ARGV), ")\n";
my $datei = shift @ARGV;
print "Erstes: $datei\n";
print "PATH vorhanden\n" if exists $ENV{PATH};
print "Skript: $0\n" if 0;
my $ausgabe = `echo Hallo vom Betriebssystem`; # Backticks: Ausgabe einfangen
print $ausgabe;
my $status = system("true"); # system: Status (0 = Erfolg)
print "Status: $status\n";
my @zeilen = `printf 'a\\nb\\n'`;
print scalar(@zeilen), " Zeilen\n";
use Getopt::Long;
@ARGV = ("--name=Mia", "--anzahl", "3", "--verbose", "rest");
GetOptions("name=s" => \my $name, "anzahl=i" => \my $anzahl, "verbose" => \my $verbose) or die;
print "name=$name anzahl=$anzahl verbose=$verbose rest=@ARGV\n";Ausgabe
Argumente: datei.txt --verbose (2) Erstes: datei.txt PATH vorhanden Hallo vom Betriebssystem Status: 0 2 Zeilen name=Mia anzahl=3 verbose=1 rest=rest
Daten aufbereiten: sprintf, sort, Reports
use strict; use warnings;
my @daten = (["Mia", 17, 1.68], ["Tom", 25, 1.82], ["Zoe", 31, 1.7]);
printf "%-6s %5s %7s\n", "Name", "Alter", "Größe";
print "-" x 20, "\n";
printf "%-6s %5d %7.2f\n", @$_ for sort { $b->[1] <=> $a->[1] } @daten;
my $csv = "name,punkte\nMia,120\nTom,80\n";
open(my $fh, '<', \$csv) or die;
my $kopf = <$fh>; chomp $kopf;
my @spalten = split /,/, $kopf;
my @zeilen;
while (<$fh>) {
chomp;
my %z; @z{@spalten} = split /,/;
push @zeilen, \%z;
}
print join(", ", map { "$_->{name}=$_->{punkte}" } @zeilen), "\n";Ausgabe
Name Alter Größe -------------------- Zoe 31 1.70 Tom 25 1.82 Mia 17 1.68 Mia=120, Tom=80
Merke
open(my $fh, '<', $pfad) or die "...: $!", Modi<>>>- Zeilenweise lesen mit
while (<$fh>)undchomp - Dateitests:
-e -f -d -s -r -w;glob,opendir,File::Spec,File::Basename,File::Temp @ARGV,%ENV, Backticks undsystem;Getopt::Longfür Optionen- UTF-8:
'<:encoding(UTF-8)'
Aufgabe
Lies eine Textdatei ein, zähle die Wörter und schreibe die zehn häufigsten in eine neue Datei.