Das Schweizer Taschenmesser für Text und Skripte
Ausführen: Datei hallo.pl speichern und mit perl hallo.pl ausführen. Einzeiler direkt mit perl -e 'print "Hallo\n"'.
use strict; use warnings;$ Skalar, @ Array, % Hashperl -ne, perl -peperl hallo.pl # Datei
perl -e 'print "Hallo\n"' # Einzeiler
perl -ne 'print if /fehler/i' log.txt # Zeilenfilter (wie grep)
perl -pe 's/alt/neu/g' datei # Filter und Ersetzen (wie sed)
perl -v # Version== < > (Zahlen) und eq lt gt (Text). verkettet, x wiederholt, length, substr, index, uc, lc, sprintf, join, split0, "0", "", undef; // für Standardwerteq(), qq(), qw() für Strings und Listenuse strict; use warnings;
my $a = 10;
my $b = "5";
print $a + $b, "\n"; # numerisch: 15
print $a . $b, "\n"; # Textverkettung: 105
print "10" == 10.0 ? "gleich\n" : "ungleich\n";
print "abc" lt "abd" ? "kleiner\n" : "größer\n";
print 7 / 2, " ", int(7 / 2), " ", 7 % 3, " ", 2 ** 10, " ", -7 % 3, "\n";
print 10 <=> 5, " ", "a" cmp "b", "\n";
my $i = 5; $i++; $i += 10; $i *= 2;
print "$i\n";
print 0.1 + 0.2 == 0.3 ? "gleich\n" : "ungleich (Gleitkomma)\n";
print abs(-3), " ", sqrt(16), " ", int(3.9), " ", sprintf("%.2f", 3.14159), "\n";
print 1_000_000 + 0x1F + 0b101 + 0o17 + 017, "\n";push, pop, shift, unshift, splice, sort, reverse, map, grep$_ ist die Standardvariable; $#a letzter Index$h{key}, keys, values, exists, delete; Reihenfolge nicht garantiertList::Util liefert sum, max, first, reduce, uniq$count{$_}++use strict; use warnings;
my @f = ("Apfel", "Birne", "Kirsche");
print "$f[0] $f[-1] $#f ", scalar(@f), "\n";
push @f, "Dattel"; # hinten anfügen
unshift @f, "Ananas"; # vorne einfügen
my $hinten = pop @f; # hinten entfernen
my $vorn = shift @f; # vorne entfernen
print "$hinten $vorn @f\n";
print "Ausschnitt: @f[0,1] | @f[1..2]\n";
splice(@f, 1, 1, "Banane", "Brombeere"); # ersetzen
print "@f\n";
my @sortiert = sort @f;
my @rueck = reverse sort @f;
print "@sortiert | @rueck\n";
my @zahlen = sort { $a <=> $b } (10, 9, 100, 1); # numerisch sortieren
print "@zahlen\n";
my @quadrate = map { $_ * $_ } 1..5;
my @gerade = grep { $_ % 2 == 0 } 1..10;
print "@quadrate | @gerade\n";
print join(", ", map { uc } @f), "\n";
my ($erstes, @rest) = (1, 2, 3, 4);
print "$erstes | @rest\n";
print "Index von Banane: ", (grep { $f[$_] eq "Banane" } 0..$#f)[0], "\n";
my @kopie = @f; # Kopie
$kopie[0] = "X";
print "$f[0] $kopie[0]\n";
print "enthalten\n" if grep { $_ eq "Dattel" } @f;
my @leer = ();
print "leer\n" unless @leer;
print scalar(@{[1..3]}), "\n";
my @mit_undef = (1, undef, 3);
print defined $mit_undef[1] ? "def" : "undef", "\n";
print "Wiederholte Liste: ", join(",", (1) x 3), "\n";if/elsif/else, unless, Modifikatoren (print ... if ...); Klammern um Bedingungen, {} immerif-Kettenfor, foreach, while, until; next, last, redo, Labelswhile (<FH>) liest zeilenweise, $. ist die Zeilennummeruse strict; use warnings;
my $punkte = 78;
if ($punkte >= 90) {
print "sehr gut\n";
} elsif ($punkte >= 75) {
print "gut\n";
} else {
print "weiter üben\n";
}
print "bestanden\n" if $punkte >= 50; # Modifikator
print "nicht perfekt\n" unless $punkte == 100;
my $text = $punkte >= 50 ? "ja" : "nein"; # ternär
print "$text\n";
print "beides\n" if $punkte > 50 and $punkte < 100;
print "oder\n" if $punkte < 0 or $punkte > 70;
print "nicht\n" if not $punkte == 0;
my $name = undef;
my $anzeige = $name // "unbekannt";
print "$anzeige\n";@_, kopiere sie mit my (...) = @_;return ist optional, mehrere Werte als Listesub f($x, $y = 1)) und say mit use v5.36;sub {...}, Referenzen \&f, Aufruf $ref->(...)wantarray erkennt den Kontext; Closures merken sich Variablenuse strict; use warnings;
sub gruss {
my ($name, $anrede) = @_;
$anrede //= "Hallo";
return "$anrede, $name!";
}
sub summe {
my $s = 0;
$s += $_ for @_; # beliebig viele Argumente
return $s;
}
sub minmax {
my @sortiert = sort { $a <=> $b } @_;
return ($sortiert[0], $sortiert[-1]); # mehrere Werte
}
sub optionen {
my (%opt) = (farbe => "blau", groesse => 10, @_); # benannte Argumente mit Standardwerten
return join(", ", map { "$_=$opt{$_}" } sort keys %opt);
}
print gruss("Mia"), "\n";
print gruss("Tom", "Hi"), "\n";
print summe(1, 2, 3, 4), "\n";
my ($klein, $gross) = minmax(5, 2, 9, 1);
print "$klein $gross\n";
print optionen(groesse => 20, rahmen => "ja"), "\n";
print "Argumente: ", scalar(@{[ 1, 2, 3 ]}), "\n";=~ /muster/ prüft, s/// ersetzt, tr/// wandelt Zeichen, qr// kompiliert$1, $2 oder %+ (benannt)i g m s x e r.+ vs. .+?@x = $s =~ /(...)/g liefert alle Trefferuse strict; use warnings;
my $text = "Mia (mia\@example.com) wohnt in 10115 Berlin, Tom (tom\@test.de) in 20095 Hamburg.";
print "gefunden\n" if $text =~ /Berlin/;
print "ohne Beachtung der Schreibweise\n" if $text =~ /BERLIN/i;
if ($text =~ /(\w+)\@(\w+)\.(\w+)/) {
print "Nutzer: $1, Domain: $2, Endung: $3\n";
}
my @mails = $text =~ /[\w.]+\@[\w.]+\w/g;
print "Mails: @mails\n";
my @plz = $text =~ /\b(\d{5})\b/g;
print "PLZ: @plz\n";
my $anzahl = () = $text =~ /\d/g;
print "Ziffern: $anzahl\n";
(my $kopie = $text) =~ s/\d{5}/#####/g;
print "$kopie\n";
my $neu = $text =~ s/Berlin/Köln/r; # /r: Kopie statt ändern
print substr($neu, 0, 40), "\n";
if ("2025-03-15" =~ /^(?<jahr>\d{4})-(?<monat>\d\d)-(?<tag>\d\d)$/) {
print "Jahr $+{jahr}, Monat $+{monat}, Tag $+{tag}\n";
}open(my $fh, '<', $pfad) or die "...: $!", Modi < > >>while (<$fh>) und chomp-e -f -d -s -r -w; glob, opendir, File::Spec, File::Basename, File::Temp@ARGV, %ENV, Backticks und system; Getopt::Long für Optionen'<:encoding(UTF-8)'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"; }\@a, \%h, \&f bilden Referenzen; [...] und {...} erzeugen anonyme$r->[0], $r->{key}, @{$r}, %{$r}, $r->@*$d{liste}[0]{name}ref() zeigt den Typ; Data::Dumper gibt Strukturen ausStorable::dclone)use strict; use warnings;
my @liste = (1, 2, 3);
my %hash = (a => 1, b => 2);
my $aref = \@liste; # Referenz auf Array
my $href = \%hash;
my $cref = sub { "Hallo $_[0]" };
my $sref = \"Text";
print "$$aref[0] ${$aref}[1] $aref->[2]\n"; # drei Schreibweisen
print "$href->{a} $$href{b}\n";
print scalar(@$aref), " Elemente\n";
print join(",", sort keys %$href), "\n";
print $cref->("Welt"), "\n";
print $$sref, "\n";
print ref($aref), " ", ref($href), " ", ref($cref), " ", ref($sref), " ", ref(\$aref), "\n";
push @$aref, 4;
print "@liste\n"; # das Original wurde geändert
my @kopie = @$aref; # echte Kopie
$kopie[0] = 99;
print "$liste[0]\n";use Modul qw(funktionen) lädt Module; viele nützliche gehören zum Kern (List::Util, POSIX, JSON::PP, Time::Piece)die und eval { } mit $@, Carp::croak für Bibliothekencpanm, metacpan.org) mit riesiger Auswahl; perldoc Modul für Dokumentationpackage, Exporter, 1; am Endeuse strict; use warnings;
use POSIX qw(floor ceil strftime);
use List::Util qw(sum max);
use Scalar::Util qw(looks_like_number blessed reftype);
use Time::Local qw(timegm);
use Text::Wrap qw(wrap);
use File::Basename;
use Cwd qw(getcwd);
print floor(3.7), " ", ceil(3.2), "\n";
print strftime("%Y-%m-%d", gmtime(timegm(0, 0, 0, 15, 2, 2025))), "\n";
print join(",", map { looks_like_number($_) ? "Zahl" : "Text" } (42, "4.5e3", "abc", "1_000")), "\n";
$Text::Wrap::columns = 20;
print wrap("", " ", "Ein langer Satz, der umgebrochen werden soll."), "\n";
print "Arbeitsverzeichnis ist nicht leer\n" if length getcwd();bless-te Referenz, Methode = Sub mit $selfuse parent, @ISA, SUPER::use overload definiert Operatoren; can, isa, ref für IntrospektionclassTest::More mit ok, is, like, is_deeply; prove führt Tests aususe strict; use warnings;
package Tier;
sub new {
my ($klasse, %args) = @_;
my $self = bless { name => $args{name} // "unbekannt", laute => 0 }, $klasse;
return $self;
}
sub name { $_[0]{name} }
sub laut { "..." }
sub vorstellen {
my $self = shift;
return sprintf("%s (%s) sagt %s", $self->name, ref($self), $self->laut);
}
package Hund;
our @ISA = ('Tier'); # Vererbung
sub laut { "Wuff" }
sub apportiere { my ($self, $was) = @_; return $self->name . " holt $was" }
package Katze;
use parent -norequire, 'Tier'; # moderner: use parent
sub new {
my ($klasse, %args) = @_;
my $self = Tier::new($klasse, %args);
$self->{leben} = $args{leben} // 9;
return $self;
}
sub laut { "Miau" }
sub vorstellen {
my $self = shift;
return $self->SUPER::vorstellen() . " und hat $self->{leben} Leben";
}
package main;
my @tiere = (Hund->new(name => "Rex"), Katze->new(name => "Mimi"));
print $_->vorstellen, "\n" for @tiere;
print $tiere[0]->apportiere("Stock"), "\n";
print $tiere[1]->isa('Tier') ? "Katze ist ein Tier\n" : "";
print Hund->can('apportiere') ? "Hund kann apportieren\n" : "";
print Katze->can('apportiere') ? "" : "Katze kann nicht apportieren\n";
my $methode = "laut";
print $tiere[0]->$methode, "\n"; # dynamischer Methodenaufrufuse strict; use warnings; und my immereq für Text, == für ZahlenTest::More$s =~ /muster/flags $s =~ s/alt/neu/flags $s =~ tr/a-z/A-Z/
Flags: i g m s x e r Gruppen: (…) (?:…) (?<name>…) Zugriff: $1 $2 $+{name} $& $` $'
\d \w \s \b . ^ $ * + ? {n,m} [abc] [^abc] a|b nicht gierig: *? +? ??