ImpressumFrank Seitz Wassermühlenstr. 2 25436 Uetersen E-Mail: fsfseitz.de Tel.: +49-176-78243503 Alle Artikel Inhaltsverzeichnis Rechtliche Hinweise Code auf GitHub Code auf meta::cpan KategorienAbonnieren |
Sonntag, 28. Mai 2023Einen minimalen Offline-Mirror des CPAN erstellenWie in Einen Offline-Mirror des CPAN erstellen beschrieben, ist es möglich, eine beliebige Kollektion von CPAN-Modulen auf einem Rechner ohne Internet-Zugang zu installieren. Der Offline-Mirror hat aktuell eine Größe von ca. 5GB. Dies läßt sich reduzieren, indem man ihn auf genau die Module beschränkt, die man tatsächlich installieren möchte. Dies geht mit Bordmitteln wie folgt:
Hierbei ist:
Mittwoch, 21. September 2022Perl: Mehrzeilige Ersetzung auf DateienIn Dateien eines Verzeichnisbaums wollen wir eine mehrzeilige Ersetzung vornehmen. Unter Nutzung von Perl geht dies mit einem Einzeiler: $ find DIR ... | xargs perl -0777 -p -i -E 's/REGEX/REPLACEMENT/gms'
Hierbei ist REGEX ein Regulärer Ausdruck, der Text über mehreren Zeilen matchen kann. Wie funktioniert der Aufruf? Perl verarbeitet die Dateien, die von xargs(1) als Argumente übergeben werden, und behandelt sie gemäß den angegebenen Optionen:
Beispiel Entferne im Verzeichnisbaum DIR die Inline-Dokumentation (POD) aus allen .pm-Dateien: $ find DIR -name '*.pm' | xargs perl -0777 -p -i -E 's/^=[a-z].*?^=cut\n//gms'
Sonntag, 14. November 2021SQLite-Datenbank von einem entfernten Rechner zugreifenSQLite ist ein leichtgewichtiges relationales Datenbanksystem, das genial konzipiert, allerdings nicht netzwerkfähig ist. Letzteres ist laut der Autoren Absicht: "SQLite is designed for situations where the data and application coexist on the same machine." Mitunter möchte man dennoch eine SQLite-Datenbank von einem entfernten Rechner zugreifen. Dass es keine gute Idee ist, wie es im Netz öfter als Lösung genannt wird, die Datenbankdatei (eine SQLite-Datenbank besteht aus einer einzigen Datei) auf ein Netzwerk-Dateisystem zu legen, wird von den Autoren in SQLite Over a Network, Caveats and Considerations dargelegt. Unter Perl lässt sich der Netzwerk-Zugriff auch solide unter Rückgriff auf DBI und dessen Proxy-Server realisieren. Der Unterschied ist, dass in dem Fall die API Schicht ins Netz verlegt wird und nicht die File-I/O Schicht (s. obiges Dokument). Starten des Proxy-Servers auf dem Rechner mit der SQLite-Datenbank: $ ssh USER@HOST "bash -lc 'dbiproxy --localport=PORT'" Zugriff auf die Datenbank aus Perl heraus von einem beliebigen Rechner aus: use DBD::SQLite;
my $dbh = DBI->connect('dbi:Proxy:hostname=HOST;port=PORT;dsn=DSN',{
RaiseError => 1,
ShowErrorStatement => 1,
});
# ab hier können wir auf die SQLite-Datenbank zugreifen, als ob sie lokal wäre
Hierbei ist:
Eine breitere Darstellung der Möglichkeiten des DBI Proxy-Servers findet sich in Programming the Perl DBI - Database Proxying. Warnung: Der DBI Proxy-Server hat offenbar ein Memory Leak und sollte daher nicht unbegrenzt lange laufen. Soll lediglich mit dem SQLite-Client auf eine entfernte Datenbank zugegriffen werden, kann dies per ssh(1) erreicht werden: $ ssh -t USER@HOST sqlite3 PATH
Sonntag, 17. Oktober 2021Ältere O'Reilly Bücher online lesen
Zahlreiche ältere Bücher von O'Reilly, die nur noch antiquarisch erhältlich sind, können hier online gelesen werden. Vieles ist veraltet, manche Themen sind jedoch nach wie vor relevant und hervorragend dargestellt. Die umfangreiche Sammlung lädt zum Stöbern ein: Beispiele:
Montag, 14. Dezember 2020PyPerler: Perl-Klassen unter Python nutzenPyPerler ist ein Python-Package mit dem es möglich ist, Perl-Code unter Python zu nutzen. Es wird vom Autor nach eigener Aussage zur Zeit nicht gepflegt, funktioniert aber recht gut (Einschränkungen siehe unten). Es lassen sich damit sogar komplexe Perl-Klassen unter Python verwenden, wie z.B. Datenbank-Operationen über einen O/R-Mapper. Ich experimentiere zur Zeit damit unter Debian 10 mit Python 3.7.3 und Perl 5.28.1. InstallationWir setzen zunächt eine virtuelle Umgebung auf, in die wir PyPerler installieren: $ virtualenv venv $ . venv/bin/activate Wir holen den Sourcecode von GitHub: $ git clone https://github.com/tkluck/pyperler.git Wir kompilieren den Code und installieren PyPerler in die virtuelle Umgebung: $ cd pyperler $ make $ make install Nun können wir Perl-Code von Python aus nutzen. Ein Beispiel findet sich im README. ProblemeOperatoren sind nicht vollständig überladenDie Operator-Methoden __radd__(), __rmul__() usw. fehlen in Klasse ScalarValue, so dass unter o.g. Python-Version ein Perl-Skalar ohne explizite Typwandlung zwar linksseitig mit einem Python-Objekt verknüpft werden kann, aber nicht rechtsseitig. Diese Definitionen lassen sich relativ einfach nachtragen. Als Richtschnur kann $ make check genutzt werden, das die Defizite aufzeigt. Die Extension ist nicht thread-savePyperler ist offenbar nicht thread-save. Eine Flask-Anwendung muss mit $ flask run --without-threads gestartet werden, sonst stürzt sie mit einem Segmentation Fault beim ersten Zugriff auf ein Perl-Objekt ab. Dies hat möglicherweise mit einem Fehler bei der Nutzung von Cythons Global Interpreter Lock (GIL) zu tun. LinksMontag, 26. September 2016Perl: Einen Offline-Mirror des CPAN erstellen
Hierbei ist:
LinksSamstag, 14. Mai 2016Ein Plugin für Mojolicious schreibenÜber die Plugin-Schnittstelle kann Mojolicious oder eine Mojolicious-Applikation um jede denkbare Funktionalität erweitert werden. Die Plugin-Schnittstelle ist sehr einfach gehalten. Denn sie gibt nur vor, wie eine Funktionalität zum System hinzugefügt wird, nicht jedoch, um welche Art von Funktionalität es sich handelt. Die Implementierung eines Mojolicious-Plugin erfolgt in zwei Schritten:
In der Dokumentation zur Basisklasse Mojolicious::Plugin wird die Implementierung so beschrieben: package Mojolicious::Plugin::MyPlugin;
use Mojo::Base 'Mojolicious::Plugin';
sub register {
my ($self, $app, $conf) = @_;
# Magic here! :)
}
Der Aufwand der Plugin-Implementierung besteht natürlich darin, den mit # Magic here! :)
bezeichneten Teil mit Leben zu füllen. Ist das Plugin implementiert, wird es durch einen einzigen Aufruf zur Applikation hinzugefügt: $app->plugin(MyPlugin => \%config);
Der analoge Aufruf unter Mojolicious::Lite: plugin MyPlugin => \%config;
Hierbei ist %config ein Hash mit Schlüssel/Wert-Paaren - typischerweise als Hash-Literal angegeben - durch den das Plugin konfiguriert wird. Ist keine Konfigurierung des Plugin nötig, kann das Argument weggelassen werden. BeispielAls einfaches Beispiel implementieren wir ein Plugin Hello, das bei jedem hereinkommenden Request die Zeichenkette 'Hello' und die IP-Adresse des Aufrufers ins Log ausgibt. Dies erreichen wir, indem wir in der Methode register() einen before_routes-Handler aufsetzen, der genau dies tut. package Mojolicious::Plugin::Hello;
Mojo::Base 'Mojolicious::Plugin';
sub register {
my ($self, $app, $conf) = @_;
$app->hook(before_routes=>sub {
my $c = shift;
$c->app->log->debug('Hello '.$c->tx->remote_address);
});
return;
}
Das Plugin wird durch $app->plugin('Hello');
oder im Falle von Mojolicious::Lite durch plugin 'Hello';
in der Applikation aktiviert. Eine Konfiguration ist bei den Aufrufen nicht angegeben, da das Plugin keine Konfigurierungsmöglichkeit vorsieht. Links zu MojoliciousMontag, 7. März 2016Perl: Programm außerhalb des Projektbaums verfügbar machenAusgangslageGegeben ein Perl-Projekt myproject mit einem eigenen Projektverzeichnis PREFIX/myproject und einer Unix-typischen Unterverzeichnisstruktur mit den Verzeichnissen bin, lib usw. PREFIX/myproject/bin/myprogram lib/perl5/MyClass.pm ... PREFIX ist ein beliebiger Verzeichnis-Pfad. Im Unterverzeichnis bin sind die Programme des Projektes installiert (hier ein Programm myprogram) und in Unterverzeichnis lib/perl5 die Module des Projektes (hier ein Modul MyClass.pm). Wir wollen das Programm myprogram nun außerhalb des Projektbaums verfügbar machen, z.B. damit es über einen allgemeinen Suchpfad aufrufbar ist, oder - falls es ein CGI-Programm ist - um es in eine Web-Verzeichnisstruktur einzufügen, ohne dass wir einen ScripAlias definieren können oder wollen. ProblemDas Problem: Außerhalb des Projektbaums installiert verliert das Programm den Bezug zum Projektverzeichnis und kann die anderen Verzeichnisse des Baums, wie z.B. das Modulverzeichnis lib/perl5 nicht ohne Weiteres adressieren. Man könnte den Pfad zum Projektverzeichnis auf einer Environment-Variablen definieren, aber das ist umständlich. LösungEin eleganterer Weg ist, das Programm per Symlink außerhalb des Projektbaums zu installieren und den realen Installationspfad des Programms mittels der Variable $RealBin des (Core-)Moduls FindBin zu ermitteln. $ ln -s PREFIX/myproject/bin/myprogram /usr/local/bin/myprogram Am Anfang von myprogram, vor dem Laden des projektspezifischen Moduls MyClass, fügen wir die beiden Zeilen ein: use FindBin qw/$RealBin/; use lib "$RealBin/../lib/perl5"; use MyClass; Der Pfad $RealBin ist das Verzeichnis, in dem das aufgerufene Programm sich befindet, und zwar nach Auflösung aller Symlinks. D.h. der Pfad ist stets PREFIX/myproject/bin auch wenn das Programm über den Pfad /usr/local/bin/myprogram aufgerufen wird. Montag, 16. November 2015Perl: Dokumentation und Kommentare aus Perl-Quelltexten entfernenEntferne POD-Abschnitte aus Perl-Quelltext: $src =~ s/^=[a-z].*?^=cut\n*//msg; Entferne ganzzeilige Kommentare aus Perl-Quelltext: $src =~ s/^[\t ]*#.*\n+//mg; Entferne teilzeilige Kommentare aus Perl-Quelltext: $src =~ s/[\t ]+# .*//g; Diese Operationen sind nützlich, wenn man einen Perl-Quelltext ohne Dokumentation und Kommentare ausliefern möchte, oder wenn man entscheiden möchte, ob eine Quelltextänderung getestet werden muss. Letzteres ist ratsam, wenn Änderungen in dem Teil des Quelltextes existieren, der übrig bleibt, wenn man die Dokumentation und die Kommentare entfernt. Als teilzeiliger Kommentar wird die Abfolge WHITESPACE-HASH-SPACE-TEXT akzeptiert. Ein teilzeiliger Kommentar muss entsprechend verfasst sein, sonst wird er nicht entfernt. Diese Einschränkung hat den Zweck, Fehl-Erkennungen zu vermeiden, denn $src =~ s/#.*//g; wäre gefährlich, da dieser Regex nach jedem HASH abschneidet. Siehe auch folgende Warnung. Warnung: Ohne echtes Parsing gemäß der Grammatik einer Sprache sind absolut sichere Operationen auf einem Quelltext nicht möglich - insbesondere bei Perl, das eine sehr facettenreiche Syntax hat. Obige Pattern können in besonderen Fällen den Inhalt von String-Literalen matchen. Im Einzelfall kann so eine Fehl-Erkennung durch Änderung des Literals - z.B. durch Einstreuen von Backslashes - verhindert werden. LinksMontag, 26. Oktober 2015Perl: Objektattributwert beim ersten Zugriff berechnenAnforderung: Ein Hash-Objekt besitzt ein Attribut theAttribute, das von einer gleichnamigen Attributmethode gekapselt wird. Das Attribut erhält bei der Objekt-Instanziierung keinen Wert. Der Wert wird stattdessen beim ersten Zugriff berechnet. Alle weiteren Zugriffe liefern den berechneten Wert. Ein naheliegender Ansatz, dies in Perl zu implementieren, ist:
Hierbei ist $val der in Abschnitt ... berechnete Attributwert (der auf dem Attribut gecached wird). Diese Lösung ist relativ hässlich, da der Ausdruck $self->{'theAttribute'} gleich drei Mal auftaucht. Zum Glück lässt sich die Sache auch eleganter formulieren:
Erklärung: Ist der Wert von theAttribute definiert, wird er unmittelbar geliefert. Ist er nicht definiert, wird der do-Block ausgeführt. Dessen Wert wird erst an das Attribut zugewiesen (=) und dann von der Methode geliefert (return). Den Defined-Or-Operator // gibt es seit Perl 5.10. Ist die Objektstruktur komplexer als ein Hash, lässt sich die Semantik von $self->{$key} //= do { ... }; auch als Objektmethode mit einer anonymen Subroutine als Parameter realisieren:
Hierbei sind get() und set() die Methoden zum Abfragen und Setzen des Attributwerts. Natürlich kann der Zugriff auf das Attribut - in Abhängigkeit von der Klasse - auch anders realisert sein. Angewendet auf obiges Beispiel:
LinksDonnerstag, 8. Oktober 2015Perl: Modulpfade ermittelnManchmal möchte man für ein Perl-Programm wissen, woher genau der Perl-Interpreter die Module lädt. Aus dem laufenden Programm heraus lässt sich dies mit folgender Zeile bestimmen: say join "\n",sort values %INC; Dasselbe mit print: print join("\n",sort values %INC),"\n"; Die Anweisung gibt die Liste der Pfade aller geladenen Module sortiert aus. Dasselbe auf der Kommandozeile, falls einen interessiert, welche Module ein bestimmtes Modul <MODULE> lädt: $ perl -M5.010 -M<MODULE> -e 'say join "\n",sort values %INC' LinksDonnerstag, 1. Oktober 2015Perl: Erreichbarkeit eines Hosts prüfenMitunter möchte man wissen, ob ein bestimmter Host erreichbar ist, z.B. vor Beginn von Regressionstests gegen Services des Hosts. Diese Prüfung kann in Perl mittels des Core-Moduls Net::Ping durchgeführt werden. use Net::Ping;
my $p = Net::Ping->new;
my $isAlive = $p->ping($host);
$p->close;
if ($isAlive) {
print "Host $host ist erreichbar\n";
}
Per Default versucht die Klasse via TCP eine Verbindung zum echo-Port aufzubauen. Für andere Möglichkeiten (Test per UDP, ICMP, ...) siehe Doku. Links
Donnerstag, 10. September 2015Perl: UTF-8 und ISO-8859-1 Dateien erkennen und automatisch dekodierenIdealerweise sollte ein Programm sowohl mit ISO-8859-1 als auch mit UTF-8 Input-Dateien umgehen können, und zwar am besten so, dass das Encoding nicht explizit angegeben werden muss. Lässt sich dies realisieren? Ja, indem das Programm sich den Inhalt der Datei "ansieht", entscheidet, welches Encoding vorliegt und den Text entsprechend dekodiert. Im Falle von Perl kann hierfür das Modul Encode::Guess genutzt werden. Es ist Teil des Perl-Core und damit in jeder Perl-Installation enthalten. Es wird mit use Encode::Guess;
geladen. Wir nutzen die objektorientierte Schnittstelle des Moduls. Theoretisch sollte folgender Sechszeiler die Aufgabe erledigen: Encode::Guess->set_suspects('iso-8859-1');
my $dec = Encode::Guess->guess($text);
if (!ref $dec) {
die "ERROR: $dec\n";
}
$text = $dec->decode($text);
Erläuterung:
Leider funktioniert diese Implementierung nicht! Denn wir stellen folgendes fest:
Woran liegt das? Die Ursache ist, dass jede UTF-8-Datei formal auch eine ISO-8859-1-Datei ist. Denn jede Datei ist formal eine ISO-8859-1-Datei, selbst eine Binärdatei wie z.B. ein JPEG-Bild. Das liegt daran, dass ISO-8859-1 ein Ein-Byte-Encoding ist, bei dem alle 256 Werte belegt sind. Es ist also fruchtlos und hinderlich, mit Encode::Guess auf ISO-8859-1 testen zu wollen. Ist die Unterscheidung von UTF-8 und ISO-8859-1 also nicht möglich? Doch, sie ist möglich, wenn auch nicht mit den Mechanismen von Encode::Guess allein. Denn auch wenn UTF-8 formal gültiges ISO-8859-1 darstellt, gilt nicht die Umkehrung, dass jeder ISO-8859-1 Text valides UTF-8 darstellt. Es ist sogar sehr unwahrscheinlich, dass ein realer ISO-8859-1 Text, gleichzeitig valides UTF-8 ergibt, beinahe ebensowenig, wie dass ein ISO-8859-1 Text ein JPEG-Bild ergibt. Unter Berücksichtigung dieser Tatsache können wir die Unterscheidung von ISO-8859-1 und UTF-8 hinreichend sicher vornehmen: my $dec = Encode::Guess->guess($text);
if (ref $dec) {
$text = $dec->decode($text);
}
elsif ($dec =~ /No appropriate encodings found/i) {
$text = Encode::decode('iso-8859-1',$text);
}
else {
die "ERROR: $dec\n";
}
Erläuterung:
Dieser Ansatz ("Wenn etwas nach UTF-8 aussieht, ist es auch UTF-8, sonst betrachten wir es als ISO-8859-1") funktioniert. Das Ganze als vollständige Implementierung einer Perl-Klasse File mit einer einzelnen Methode decode(): package File;
use strict;
use warnings;
use Encode::Guess ();
# ---------------------------------------------------------------------------
=encoding utf8
=head1 NAME
File - Klasse mit Datei-Operationen
=head1 METHODS
=head2 decode() - Lies und dekodiere eine Textdatei
=head3 Synopsis
$text = $class->decode($file);
=head3 Description
Lies Textdatei $file und liefere den dekodierten Inhalt zurück.
Als Character Encoding erwarten wir Unicode (speziell UTF-8) oder
Latin1 (ISO-8859-1).
=cut
# ---------------------------------------------------------------------------
sub decode {
my ($class,$file) = @_;
# Datei einlesen
local $/ = undef;
open my $fh,'<',$file or die "ERROR: open failed: $file ($!)\n";
my $text = <$fh>;
close $fh;
# Encoding ermitteln und Text dekodieren
my $dec = Encode::Guess->guess($text);
if (ref $dec) {
# Wir dekodieren Unicode
$text = $dec->decode($text);
}
elsif ($dec =~ /No appropriate encodings found/i) {
# Erwarteter Fehler: Wir dekodieren Latin1
$text = Encode::decode('iso-8859-1',$text);
}
else {
# Unerwarteter Fehler
die "ERROR: $dec\n";
}
return $text;
}
# ---------------------------------------------------------------------------
=head1 AUTHOR
Frank Seitz, L<http://fseitz.de/>
=head1 LICENSE
This code is free software. You can redistribute it and/or modify
it under the same terms as Perl itself.
=cut
# ---------------------------------------------------------------------------
1;
# eof
LinksFreitag, 31. Juli 2015Perl: Module installieren mit cpanmEin hervorragendes Werkzeug zum Installieren von Perl-Modulen ist cpanm ("cpanminus"). Nach dem Kompilieren und Installieren von Perl aus den Quellen per $ ./Configure -des -Dprefix=~ $ make test $ make install und der Installation von cpanm per $ curl -L http://cpanmin.us | `which perl` - --self-upgrade kann man jedes (naja, fast jedes) CPAN-Modul mit einem simplen Aufruf zur Installation hinzufügen: $ ~/bin/cpanm MODULE Abhängkeiten von anderen Modulen werden erkannt und rekursiv aufgelöst. Das Programm cpanm lässt sich auch standalone an Ort und Stelle installieren (aus App::cpanminus): cd ~/bin curl -LO http://xrl.us/cpanm chmod +x cpanm # edit shebang if you don't have /usr/bin/env Modul MODULE mit allen zusätzlich benötigten (non-core) Modulen in Verzeichnis DIR installieren, um sie auf eine andere Maschine zu übertragen: $ cpanm -L DIR MODULE Z.B. $ cpanm -L perl5 File::Rsync --> Working on File::Rsync Fetching http://www.cpan.org/authors/id/L/LE/LEAKIN/File-Rsync-0.49.tar.gz ... OK Configuring File-Rsync-0.49 ... OK ==> Found dependencies: IPC::Run3 --> Working on IPC::Run3 Fetching http://www.cpan.org/authors/id/R/RJ/RJBS/IPC-Run3-0.048.tar.gz ... OK Configuring IPC-Run3-0.048 ... OK Building and testing IPC-Run3-0.048 ... OK Successfully installed IPC-Run3-0.048 Building and testing File-Rsync-0.49 ... OK Successfully installed File-Rsync-0.49 2 distributions installed Freitag, 10. Juli 2015Perl: Hostname zu IP-Adresse ermittelnBei der Auswertung von HTTP-Zugriffen möchte man u.U. die IP-Adressen zu Hostnamen auflösen. Das geht in Perl so:
Zwei Punkte sollte man dabei im Hinterkopf behalten:
Freitag, 3. Juli 2015Perl: Speedy (CGI-SpeedyCGI) unter Perl 5.10 und höher kompilierenDer schon etwas in die Jahre gekommene, aber für Webanwendungen immer noch hervorragende persistente Perl-Interpreter speedy kompiliert unter neueren Perl-Versionen nicht mehr. Der Versuch endet mit dem Fehler: speedy_perl.c: In function ?find_scr?: speedy_perl.c:258:24: error: expected expression before ?SpeedyScript? speedy_new(retval, 1, SpeedyScript); ^ ../src/speedy_backend_main.h:41:39: note: in definition of macro ?speedy_new? #define speedy_new(s,n,t) New(123,s,n,t) Ursache ist, dass das C-Makro New() aus dem Perl-CORE (CORE/handy.h), nicht mehr existiert. Dies ist offenbar seit Perl 5.10 der Fall. Die Lösung ist, anstelle des Makros New() das Makro Newx() zu benutzen. Hierzu muss in src/speedy_backend_main.h #define speedy_new(s,n,t) New(123,s,n,t) durch #define speedy_new(s,n,t) Newx(s,n,t) ersetzt werden. Dann kompilieren die Quellen fehlerfrei. Getestet unter Perl 5.20.2. Ein weiteres Problem tritt bei Perl 5.22.1 (mit gcc 5.3.1) auf: In file included from ../src/speedy_inc.h:90:0, from speedy.h:2, from speedy_backend_main.c:24: ../src/speedy_file.h:54:19: warning: inline function ?speedy_file_set_state? declared but never defined SPEEDY_INLINE int speedy_file_set_state(int new_state); ^ Dies lässt sich dadurch beheben, dass in src/speedy_inc.h die Macro-Definition SPEEDY_INLINE geändert wird zu #ifdef __GNUC__ #define SPEEDY_INLINE /* __inline__ */ #else #define SPEEDY_INLINE #endif Zum Testen (Perl 5.28.1) muss entgegen dem üblichen make test im Wurzelverzeichnis erst in das Unterverzeichnis speedy gewechselt werden: $ cd speedy $ make test Montag, 8. Juni 2015Perl: Text im richtigen Character Encoding ausgebenJedes Kommandozeilenprogramm, das Texte und Meldungen mit Non-ASCII-Zeichen (z.B. Umlauten) aufs Terminal ausgibt, sollte die aktuelle Locale-Einstellung berücksichtigen, damit sichergestellt ist, dass alle Zeichen richtig dargestellt werden. Es reicht nicht aus, dass die Ausgabe unter der eigenen Terminal-Einstellung (z.B LANG=xx_XX.UTF-8) korrekt aussieht. Denn hat der Anwender ein abweichendes Character-Encoding konfiguriert (z.B. LANG=xx_XX.ISO-8859-1), sieht er anstelle der Non-ASCII-Zeichen Zeichensalat, wenn das Programm nicht explizit in dieses Encoding wandelt (in diesem Fall sähe er zwei Zeichen statt einem für jeden Umlaut). In Perl lässt sich diese nicht-triviale Aufgabe elegant durch Verwendung des Pragma open in Verbindung mit der Angabe ':locale' lösen. Die Zeile use open OUT=>':locale'; am Anfang des Programms sorgt dafür, dass für alle Ausgabeströme (einschl. STDOUT und STDERR) ein I/O-Layer eingerichtet wird, der die geschriebenen Daten automatisch gemäß dem in der Umgebung eingestellten Character-Encoding enkodiert. Beispiel: Die folgenden beiden Programme geben für beliebig in der Umgebung eingestellte Zeichensätze mit deutschen Umlauten - u.a. UTF-8 und ISO-8859-1 - zwei Zeilen mit Umlauten aus, die korrekt dargestellt sein sollten. Hierbei erzeugt print die Ausgabe via STDOUT und warn die Ausgabe via STDERR. Quelle mit einem Latin1-Editor erstellt: #!/usr/bin/env perl
use strict;
use warnings;
use open OUT=>':locale';
my $str = "ÄÖÜäöüß";
print "$str\n";
warn "$str\n";
# eof .
Quelle mit einem UTF-8-Editor erstellt: #!/usr/bin/env perl
use strict;
use warnings;
use utf8; # <- UTF-8 Quelltext
use open OUT=>':locale';
my $str = "ÄÖÜäöüß";
print "$str\n";
warn "$str\n";
# eof .
LinksSamstag, 22. Juni 2013Perl: Web Services mit SOAP::WSDL ansprechenDas Perl-Modul SOAP::WSDL stellt Mittel bereit, um Web Services ansprechen zu können, für die eine WSDL-Definition existiert. Der bevorzugte Weg ist, aus der WSDL-Definition eine Client-Schnittstelle zu generieren und diese zur Interaktion mit dem Web-Service zu nutzen. Die generierte Schnittstelle ist objektorientiert, besteht also aus einer Sammlung von Klassen. Die Schnittstelle wird von dem Programm wsdl2perl.pl generiert, das Bestandteil des Moduls SOAP::WSDL ist. Ein typischer Aufruf ist: $ wsdl2perl.pl -b DIR -p PREFIX URL DIR : Zielverzeichnis (Default: ".") PREFIX : Präfix für alle generierten Klasse (Default: "My") URL : URL der WSDL-Definition BeispielDer Web Service "Global Weather" ist ein einfacher Dienst, der aktuelle Wetterinformation über größere Städte der Welt liefert. Als Ausgangsinformation steht zur Verfügung:
Aus der formalen WSDL-Definition generieren wir mittels wsdl2perl.pl eine objektorientierte Client-Schnittstelle für Perl: $ wsdl2perl.pl -b lib -p GW:: http://www.webservicex.net/globalweather.asmx?wsdl Creating element class GW/Elements/GetWeather.pm Creating element class GW/Elements/GetWeatherResponse.pm Creating element class GW/Elements/GetCitiesByCountry.pm Creating element class GW/Elements/GetCitiesByCountryResponse.pm Creating element class GW/Elements/string.pm Creating typemap class GW/Typemaps/GlobalWeather.pm Creating interface class GW/Interfaces/GlobalWeather/GlobalWeatherSoap.pm Nun können wir einen Client programmieren, der das Wetter abfragt: #!/usr/bin/env perl
use strict;
use warnings;
use lib 'lib';
use GW::Interfaces::GlobalWeather::GlobalWeatherSoap;
if (@ARGV != 2) {
die "Usage: gw COUNTRY CITY\n";
}
my ($country,$city) = @ARGV;
my $soap = GW::Interfaces::GlobalWeather::GlobalWeatherSoap->new;
my $res = $soap->GetWeather({
CountryName=>$country,
CityName=>$city,
});
printf "%s\n",$res->get_GetWeatherResult;
Aufruf und Resultat: $ gw germany hamburg <?xml version="1.0" encoding="utf-16"?> <CurrentWeather> <Location>Hamburg-Finkenwerder, Germany (EDHI) 53-32N 009-50E 13M</Location> <Time>Jun 22, 2013 - 09:20 AM EDT / 2013.06.22 1320 UTC</Time> <Wind> from the SSW (200 degrees) at 15 MPH (13 KT) (direction variable):0</Wind> <Visibility> greater than 7 mile(s):0</Visibility> <SkyConditions> mostly cloudy</SkyConditions> <Temperature> 69 F (21 C)</Temperature> <DewPoint> 57 F (14 C)</DewPoint> <RelativeHumidity> 64%</RelativeHumidity> <Pressure> 29.85 in. Hg (1011 hPa)</Pressure> <Status>Success</Status> </CurrentWeather> Montag, 17. Juni 2013Eclipse: EPIC-Plugin für Perl installierenInstallation von EPIC unter Eclipse 3.8
Behandlung von TabsWindow -> Preferences -> Perl EPIC -> Editor Displayed tab width: 4 Insert tabs/spaces on indent: 1->4 [x] use spaces instead of tabs Zeilen umbrechenWindow -> Preferences -> Perl EPIC -> Editor [x] Wrap lines Perl-Projekt anlegenFile -> New -> Project... Perl Project Fontgröße einstellenWindow -> Preferences -> General -> Appearence -> Colors and Fonts Doppelklick auf "Text Font". Dort die Fontgröße auswählen. Montag, 4. März 2013Perl: Testsuite auf Basis des Test Anything Protocol (TAP)Protokoll und KomponentenDas Test Anything Protocol (TAP) definiert eine textorientierte Kommunikationsschnittstelle zwischen Programmen, die Tests durchführen, den sogenannten Produzenten des Protokolls, und Steuer- und Auswertungsprogrammen, die Testprogramme aufrufen, deren Ergebnisse einsammeln und anzeigen, den sogenannten Konsumenten des Protokolls.
Die genannten Klassen sind im Perl Core, also unter jeder neueren Perl-Installation von Hause aus verfügbar. Objektorientierte Überdeckung für Test::MoreDie Klasse Test::Builder stellt eine Grundlage (Basisklasse) für das Schreiben von Testprogrammen dar. Die Klasse erlaubt, das Test Anything Protocol in vollem Umfang "zu sprechen". Allerdings implementiert die Klasse nur einen begrenzten Umfang an Testmethoden: ok is_eq is_num isnt_eq isnt_num like unlike cmp_ok Eine andere Möglichkeit besteht darin, das Core-Modul Test::More zu nutzen, das auf Test::Builder aufbaut und u.a. die sehr wichtige Funktion is_deeply (Vergleich von Datenstrukturen) zur Verfügung stellt. Der Nachteil von Test::More ist allerdings, dass es nur eine Funktionssammlung, keine Klasse ist. Wer objektorientiert arbeiten möchte, findet das eventuell nicht so gut. Es lässt sich aber leicht eine saubere objektorientierte Überdeckung für Test::More schreiben, wenn man einige Punkte beachtet. Hier eine objektorientierte Hülle für is_deeply, die analog auf alle Testfunktionen von Test::More ausgedehnt werden kann: 1 use Test::More (); 2 3 sub is_deeply { 4 my ($self,$ref1,$ref2,$text) = @_; 5 6 local $Test::Builder::Level = $Test::Builder::Level + 1; 7 return Test::More::is_deeply($ref1,$ref2,$text); 8 } Erklärung der Besonderheiten:
Freitag, 14. Oktober 2011Perl: Klassische Formularprogrammierung(dieser Eintrag wird fortgeführt) Die Eingabeelemente eines Web-Formulars empfangen ihre Werte idealerweise aus dem Request-Objekt. Drei Fälle sind zu unterscheiden:
In Perl:
$cgi ist das Request-Objekt. $action zeigt an, ob die Daten nach einem Submit an das Formular zurückgeliefert wurden. Die Formularwerte kommen dann aus den CGI-Parametern. $objId ist die Id des Modell-Objekts. Wenn $action nicht gesetzt ist, wird das Formular aus dessen Attributen initialisiert. Object ist die Modell-Klasse. Diese implementiert die Methode copyTo(), welche die Datensatz-Attribute auf das Request-Objekt kopiert. $db ist das Datenbank-Objekt, über das auf ddie Datenbank zugegriffen wird. @keyVal ist die Liste aus Schlüssel/Wert-Paaren für die Initialisierung mit den Defaultwerten. Freitag, 28. Januar 2011mod_perl: Eigenen Perl-Interpreter für Virtual HostPer Default wird bei mod_perl derselbe Perl-Interpreter für alle Virtual Hosts genutzt. Das kann zu Problemen führen, wenn die Applikationen unterschiedliche Versionen derselben Module nutzen. Dies kann bei mod_perl 2.0 mit der PerlOption +Clone ausgeschlossen werden: <VirtualHost ...> PerlOptions +Clone </VirtualHost> Die Option +Clone bewirkt, dass für den betreffenden Virtual Host ein eigener Interpreter-Pool genutzt wird. Dieser entsteht durch Klonen des Parent-Interpreters (welcher eventuell schon eine Startup-Initialisierung erfahren hat). Ein Interpreter-Pool mit einem gänzlich neuen Parent-Interpreter wird bei Angabe von +Parent erzeugt: <VirtualHost ...> PerlOptions +Parent </VirtualHost> Um dem Interpreter einen (oder mehrere) eigene Suchpfade mitzugeben, kann die Perl Standard-Option -I verwendet werden: PerlSwitches -I/var/www1/modules Donnerstag, 21. Oktober 2010Perl: Apache2::Reload installierenApache2::Reload ist ein Perl-Modul, das Module einer mod_perl-Applikation automatisch neu lädt, wenn diese geändert wurden. Andernfalls müsste der HTTP-Server neu gestartet werden um die Änderungen sichtbar zu machen, was während der Entwicklung umständlich ist und Zeit kostet.
Donnerstag, 20. Mai 2010Perl: POD als Programm-HilfetextDas Core-Modul Pod::Usage kann einen Programm-Hilfetext aus der eingebetteten POD-Dokumentation generieren. Es geht auch einfacher:
produziert auf STDOUT NAME myprog - a simple program LICENSE This program is free software; you can redistribute it and/or modify it under the same terms as Perl itself. Donnerstag, 25. März 2010Perl: Plus / Minus UnendlichPerl kennt mehrere Zeichenketten, die - numerisch interpretiert - plus und minus Unendlich bedeuten.
Beispiel: Maximum ermitteln
Aber Achtung: Diese besonderen Werte sind nicht sonderlich gut dokumentiert und scheinen bei einigen Windows-Ports nicht zu funktionieren. Siehe: Unendliches Perl... Donnerstag, 18. März 2010Perl: Dirhandles objektorientiertAnalog zu lexikalischen Filehandles besitzt Perl lexikalische Dirhandles. Eine Dirhandle ist ein Iterator über einem Verzeichnis. Die Operationen auf Dirhandles lassen sich objektorientiert kapseln. Hier eine entsprechende Klasse Dirhandle mit drei Methoden: new() (Directory öffnen), close() (Directory schließen) und next() (nächster Directory-Eintrag):
Beispiel: Gib alle Einträge des Verzeichnisses $dir auf STDOUT aus 1 use Dirhandle; 2 3 my $dh = Dirhandle->new($dir); 4 while (my $entry = $dh->next) { 5 say $entry; 6 } 7 $dh->close; Das Dirhandle-Objekt $dh kann wie jede normale Dirhandle an die Perl-Builtins readdir(), telldir(), seekdir(), rewinddir(), closedir() übergeben werden. Dienstag, 16. März 2010Perl: Filehandles objektorientiertMit lexikalischen Filehandles ist es in Perl leicht möglich, File-I/O objektorientiert zu kapseln. Hier zur Veranschaulichung eine Klasse Filehandle mit drei Methoden: new() (Datei öffnen), close() (Datei schließen) und slurp() (Datei komplett einlesen):
Beispiel: Lies eine Datei komplett ein und gib sie auf STDOUT aus 1 use Filehandle; 2 3 my $fh = Filehandle->new('<',$file); 4 print $fh->slurp; 5 $fh->close; Der Clou: Die Filehandle $fh kann unabhängig von der Klasse wie jede andere Perl-Filehandle benutzt werden, z.B. mit dem Diamant-Operator <> oder jeder anderen Filehandle-Operation wie read(), write() usw. Obiges Programm lässt sich also auch so implementieren: 1 use Filehandle; 2 3 my $fh = Filehandle->new('<',$file); 4 while (<$fh>) { 5 print; 6 } 7 $fh->close; Freitag, 5. März 2010Perl: Crash bei Umleitung von STDERR auf Skalare VariableIch weiß nicht, wann Perl mir mal abgestürzt ist, aber jetzt bin ich auf einen Fall gestoßen:
Aufruf: $ ./test.pl Segmentation fault Perl-Version (andere habe ich nicht probiert): $ perl -v This is perl, v5.10.1 (*) built for i686-linux VariationenWenn $s kein In-Memory File ist, geht es. Bei $s =~ s/./xx/; geht es (ohne g Modifier). Bei $s =~ s/./x/g; geht es (der String wird nicht länger). Schließen von STDERR vor dem s/// ändert nichts. Freitag, 5. Februar 2010Syntax-Highlighting mit perltidyPertidy stellt die Syntax von Perl-Code farbig und mit Fontattributen wie kursiv und fett dar, wenn man den Code mit Option -html nach HTML wandelt. Ich nutze dieses Feature, um gut lesbareren Perl-Code für mein Blog zu generieren. Für die Einbettung des generierten HTML-Codes in eigene HTML-Seiten sind allerdings kleinere Sonderbehandlungen nötig. Anpassung der Stylesheet-DefinitionenPerltidy generiert mit $ perltidy -html -ss >FILE.css eine Stylesheet-Datei, die die Definitionen der CSS-Klassen für die Syntaxelemente enthält und in die eigenen HTML-Seiten eingebunden werden kann: Command failed: ./blog-highlight CSS ehtml Anpassung 1Die CSS-Definitionen für <body> und <pre> am Anfang sollten im Falle einer Einbettung nicht vorkommen, da diese an anderer Stelle definiert sind. Sie lassen sich mit grep wegfiltern. $ perltidy -html -ss | grep '^\.' Anpassung 2Die Namen der CSS-Klassen bestehen aus ein oder zwei Buchstaben, was zu Nameclashes führen kann. Dies verbessere ich, indem ich dem Klassennamen einen Präfix voranstelle. Ich wähle "pt-". $ perltidy -html -ss | grep '^\.' | sed -e 's/^\./.pt-/' Resultierende CSS-DateiCommand failed: ./blog-highlight CSS ehtml Anpassung des HTML-CodesPerltidy erzeugt mit $ perltidy -html -pre <FILE >FILE.html eine Quelltext-Darstellung in HTML. Diese kann in die eigene Seite eingebunden werden. Anpassung 1Der HTML-Code ist in ein <pre> ohne CSS-Klassenangabe eingefasst. Das CSS-Layout dieses <pre> lässt sich also nicht gezielt anpassen. Am besten filtert man es weg und setzt den HTML-Code in ein eigenes <pre>. $ perltidy -html -pre <FILE | egrep -v '^</?pre>' Anpassung 2Die CSS-Klassennamen müssen an die oben gewählten Namen in der Stylesheet-Datei angepasst werden. $ perltidy -html -pre | egrep -v '^</?pre>' | sed -e 's/class="/class="pt-/g' Resultierender HTML-CodeAus print "Hello world!\n"; wird im HTML-Output (Umbruch hinzugefügt) <span class="pt-k">print</span> <span class="pt-q"> "Hello world!\n"</span><span class="pt-sc">;</span> und im Browser print "Hello world!\n"; LinksDonnerstag, 4. Februar 2010Perl: Effizient Zeichen zählenIst eine FAQ (s. perldoc -q occurrences), aber ich vergesse immer die genaue Syntax, da ich tr/// selten nutze und es mehrere Funktionen in sich vereint: $n = $str =~ tr/\n//; $n ist in diesem Fall die Anzahl der Zeilenumbrüche in $str. Mittwoch, 27. Januar 2010Perl: Gleitkomma-Zahlen ausgeben wie sie sindVielleicht trivial, aber mir war die Antwort bislang nicht klar: Wie gebe ich eine Gleitkomma-Zahl aus, ohne dass Stellen wegfallen oder überflüssige Nullen am Ende erscheinen? Bei der Ausgabe von Gleitkommazahlen habe ich bislang automatisch zu printf/sprintf und %f gegriffen, aber das Format-Element %f formatiert die Zahlen ja immer auf eine feste Anzahl an Stellen und rundet auf die letzte Stelle. Z.B. my $x = 0.123456789; printf "%f",$x; ergibt 0.123457 (%f formatiert/rundet per Default auf 6 Nachkommastellen) Natürlich kann ich die Anzahl der Stellen groß wählen, aber dann bekomme ich u.U. zusätzliche Stellen, wenn die betreffende Zahl binär nur näherungsweise dargestellt werden kann: my $x = 0.123456789; printf "%.20f",$x; ergibt 0.12345678899999999734 Andererseits erhalte ich am Ende überflüssige Nullen bei Zahlen, die dezimal weniger als die vorgegebenen Stellen besitzen: my $x = 0.5; printf "%.20f",$x; ergibt 0.50000000000000000000 Was tun? Die Lösung ist (anscheinend) einfach: Ich gebe die Zahl nicht als Zahl sondern als String aus! D.h. im Falle von printf/sprintf mit Format-Element %s! Damit erhalte ich, was ich will. Die Zahl mit allen Stellen und nicht mehr my $x = 0.123456789; printf "%s",$x; -> 0.123456789 und ohne überflüssige Nullen my $x = 0.5; printf "%s",$x; -> 0.5 Bei näherer Überlegung leuchtet das ein, da Perl intern neben der (binären) numerischen Repräsentation eine Stringrepräsentation des Werts speichert, welche anfänglich genau der Zeichenfolge bei der Zuweisung entspricht. Schlussfolgerung: Programme, die nicht rechnen, sondern Gleitkommazahlen nur einlesen und wieder ausgeben, sollten, um Verfälschungen auszuschließen, diese bei der Ausgabe grundsätzlich als Strings und nicht als Zahlen behandeln. Mittwoch, 20. Januar 2010Perl: Operationen auf SymlinksFür den Umgang mit Symlinks stellt Perl eine Reihe von Builtins zur Verfügung, die nicht unbedingt offensichtlich sind. Hier eine kurze Übersicht: Test auf Symlink: $bool = -l $path; Dateisystem-Eigenschaften des Symlink: @stat = lstat $path; Ziel des Symlink: $destPath = readlink $path; Erstelle Symlink $path mit Ziel $destPath, liefert 0 im Fehlerfall: $bool = symlink $path,$destPath; Dienstag, 19. Januar 2010Liste der zusätzlich installierten Perl-ModuleWie ermittele ich, welche Perl-Module über das Grundsystem hinaus installiert wurden? Die Antwort liefert das Kommando: $ perldoc perllocal Das Ergebnis ist ein formatiertes POD-Dokument, das die Installationshistorie aller per make install oder ./Build install installierten Module aufführt. Das Dokument wird mit der Installation des ersten Moduls angelegt. Unmittelbar nach Installation des Core-Systems ist es noch nicht vorhanden, da noch kein zusätzliches Modul installiert wurde. Mit jeder Modul-Installation wird ein Eintrag am Ende hinzugefügt. Wird ein Modul mehrfach installiert, taucht es mehrfach auf. ProgrammLiefere die Namen der zusätzlich installierten Module, alphabetisch sortiert, ohne Dubletten: 1 #!/usr/bin/env perl 2 3 use strict; 4 use warnings; 5 6 my %mod; 7 my $cmd = 'perldoc -u perllocal'; 8 open(my $fh,'-|',$cmd) or die "ERROR: open failed ($!)"; 9 while (<$fh>) { 10 if (/^=head2.*\|(.*)>/) { 11 $mod{$1} = 1; 12 } 13 } 14 close($fh) or die qq|ERROR: Command failed: "$cmd" (Exit Code: $?)\n|; 15 16 for my $mod (sort keys %mod) { 17 print "$mod\n"; 18 } 19 20 # eof Dienstag, 12. Januar 2010Speicherbedarf von Perl-VariablenDer Speicherbedarf von einzelnen Perl-Variablen und komplexeren Datenstrukturen lässt sich mit Devel::Size ermitteln. Hier die Werte für Perl 5.10 auf einem 32-Bit System. (Eine andere Betrachtung - Messung des verbrauchten virtuellen Speichers bei großen Datenstrukturen - hat Peter J. Holzer angestellt: http://www.hjp.at/programming/perl/memory/) Skalare
Perl alloziert bei Strings jeweils 4 Bytes im Voraus, vermutlich um jedes UTF-8 Zeichen speichern zu können. Obige Berechnung geht von 1-Byte-Zeichen aus. Enthält der String UTF-8 Zeichen mit 2, 3 oder 4 Byte, vergrößert sich der Platzbedarf entsprechend. Arrays
Perl vergrößert ein Array schrittweise auf 4, 8, 16, 32, 64, ... Elemente. D.h. wird das 4. Element zugewiesen, vergößert Perl intern schon auf 8 Elemente usw. Für jedes Element alloziert Perl einen Pointer (4 Bytes). Die angegebene Größe ist der Netto-Speicherbedarf des Array, d.h. der Speicherbedarf der (skalaren) Werte kommt noch hinzu. Hashes
Perl vergrößert einen Hash schrittweise auf 8, 16, 32, 64, ... Elemente. D.h. wird das 8. Element zugewiesen, vergößert Perl intern auf 16 Elemente usw. Für jeden Key alloziert Perl vorab einen Pointer (4 Bytes). Zusätzlich kommt mit zunehmender Anzahl Buckets ein wachsender Overhead von 9, 10, 11, ... Bytes je Key hinzu. Die Größe des Key geht auch mit ein. Bei der Messung unten ist der Key der String "EintragNNNN", also 11 Zeichen lang. Die angegebene Größe ist der Netto-Speicherbedarf des Hash, d.h. der Speicherbedarf der Werte kommt noch hinzu. MessungPerl Version: 5.026000 Skalar ohne Wert: 24 Bytes Referenz: 24 Bytes Integer: 24 Bytes Float: 24 Bytes String - leer: 42 Bytes String - 1 1-Byte Zeichen: 42 Bytes (Diff: 0) String - 2 1-Byte Zeichen: 42 Bytes (Diff: 0) String - 3 1-Byte Zeichen: 42 Bytes (Diff: 0) String - 4 1-Byte Zeichen: 42 Bytes (Diff: 0) String - 5 1-Byte Zeichen: 42 Bytes (Diff: 0) String - 6 1-Byte Zeichen: 42 Bytes (Diff: 0) String - 7 1-Byte Zeichen: 42 Bytes (Diff: 0) String - 8 1-Byte Zeichen: 42 Bytes (Diff: 0) String - 9 1-Byte Zeichen: 42 Bytes (Diff: 0) String - 10 1-Byte Zeichen: 48 Bytes (Diff: 6) String - 11 1-Byte Zeichen: 48 Bytes (Diff: 0) String - 12 1-Byte Zeichen: 48 Bytes (Diff: 0) String - 16 1-Byte Zeichen: 56 Bytes (Diff: 8) String - 20 1-Byte Zeichen: 56 Bytes (Diff: 0) Array - leer: 64 Bytes Array - 4 Elemente: 96 Bytes (Diff: 32) - 24.0 Bytes/Key Array - 8 Elemente: 128 Bytes (Diff: 32) - 16.0 Bytes/Key Array - 16 Elemente: 200 Bytes (Diff: 72) - 12.5 Bytes/Key Array - 32 Elemente: 344 Bytes (Diff: 144) - 10.8 Bytes/Key Array - 64 Elemente: 624 Bytes (Diff: 280) - 9.8 Bytes/Key Hash - leer: 120 Bytes Hash - 4 Keys: 396 Bytes (Diff: 276) - 99.0 Bytes/Key Hash - 8 Keys: 736 Bytes (Diff: 340) - 92.0 Bytes/Key Hash - 16 Keys: 1416 Bytes (Diff: 680) - 88.5 Bytes/Key Hash - 32 Keys: 2776 Bytes (Diff: 1360) - 86.8 Bytes/Key Hash - 64 Keys: 5496 Bytes (Diff: 2720) - 85.9 Bytes/Key Hash - 128 Keys: 10936 Bytes (Diff: 5440) - 85.4 Bytes/Key Hash - 256 Keys: 21872 Bytes (Diff: 10936) - 85.4 Bytes/Key Hash - 512 Keys: 43632 Bytes (Diff: 21760) - 85.2 Bytes/Key Hash - 1024 Keys: 87152 Bytes (Diff: 43520) - 85.1 Bytes/Key Programm1 #!/usr/bin/env perl 2 3 use strict; 4 use warnings; 5 6 use Devel::Size; 7 8 print "Perl Version: $]\n"; 9 10 my $s1; 11 print 'Skalar ohne Wert: ',Devel::Size::size(\$s1)," Bytes\n"; 12 13 my $s2 = \$s1; 14 print 'Referenz: ',Devel::Size::size(\$s2)," Bytes\n"; 15 16 my $s3 = 4711; 17 print 'Integer: ',Devel::Size::size(\$s3)," Bytes\n"; 18 19 my $s4 = 1234.567; 20 print 'Float: ',Devel::Size::size(\$s4)," Bytes\n"; 21 22 my $s5 = ''; 23 my $nLast = Devel::Size::size(\$s5); 24 print "String - leer: $nLast Bytes\n"; 25 26 for my $i (1..12,16,20) { 27 $s5 = 'x'x$i; 28 my $n = Devel::Size::size(\$s5); 29 print "String - $i 1-Byte Zeichen: $n Bytes (Diff: ",$n-$nLast,")\n"; 30 $nLast = $n; 31 } 32 33 my @a1; 34 $nLast = Devel::Size::size(\@a1); 35 print "Array - leer: $nLast Bytes\n"; 36 37 for my $i (4,8,16,32,64) { 38 my @a2 = (1..$i); 39 my $n = Devel::Size::size(\@a2); 40 my $diff = $n-$nLast; 41 my $avg = $n/$i; 42 printf "Array - $i Elemente: $n Bytes (Diff: $diff) - %.1f Bytes/Key\n", 43 $avg; 44 $nLast = $n; 45 } 46 47 my %h1; 48 $nLast = Devel::Size::size(\%h1); 49 print "Hash - leer: $nLast Bytes\n"; 50 51 for my $i (4,8,16,32,64,128,256,512,1024) { 52 my %h2; 53 for (my $j = 1; $j <= $i; $j++) { 54 $h2{sprintf 'Eintrag%04d',$j} = $j; 55 } 56 # @h2{(1..$i)} = (1..$i); 57 my $n = Devel::Size::size(\%h2); 58 my $diff = $n-$nLast; 59 my $avg = $n/$i; 60 printf "Hash - $i Keys: $n Bytes (Diff: $diff) - %.1f Bytes/Key\n",$avg; 61 $nLast = $n; 62 } 63 64 # eof Montag, 4. Januar 2010Perl-Interpreter über Shebang-Zeile suchenMit folgender Shebang-Zeile wird der Perl-Interpreter über die Environment-Variable $PATH gesucht: #!/usr/bin/env perl D.h. die Shebang-Zeile muss nicht angepasst werden, wenn das Skript in mehreren Umgebungen mit unterschiedlichen Perl-Installationspfaden laufen soll.
(Seite 1 von 1, insgesamt 35 Einträge)
|
Kalender
StatistikLetzter Artikel:
08.07.2024 21:11 157 Artikel insgesamt
Links
|