Impressum![]() Frank Seitz Hauptstr. 32-34 25462 Rellingen E-Mail: fs ![]() Tel.: +49-176-78243503 Freiberufler-Profil Profil auf XING Artikel Inhaltsverzeichnis Rechtliche Hinweise Quellen auf GitHub Quellen auf meta::cpan Kategorien |
Montag, 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:
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:
Der analoge Aufruf unter Mojolicious::Lite:
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. Das Plugin wird durch
oder im Falle von Mojolicious::Lite durch
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 Host prüfenMitunter möchte man wissen, ob ein bestimmter Host erreichbar ist, z.B. vor Beginn von Regressionstests gegen Services des Host. Diese Prüfung kann in Perl mittels des Core-Moduls Net::Ping durchgeführt werden.
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
geladen. Wir nutzen die objektorientierte Schnittstelle des Moduls. Theoretisch sollte folgender Sechszeiler die Aufgabe erledigen:
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:
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(): 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 | ~/bin/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 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:
Quelle mit einem UTF-8-Editor erstellt:
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: 1 #!/usr/bin/env perl 2 3 use strict; 4 use warnings; 5 6 use lib 'lib'; 7 use GW::Interfaces::GlobalWeather::GlobalWeatherSoap; 8 9 if (@ARGV != 2) { 10 die "Usage: gw COUNTRY CITY\n"; 11 } 12 my ($country,$city) = @ARGV; 13 14 my $soap = GW::Interfaces::GlobalWeather::GlobalWeatherSoap->new; 15 16 my $res = $soap->GetWeather({ 17 CountryName=>$country, 18 CityName=>$city, 19 }); 20 21 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: /* default style sheet generated by perltidy */ body {background: #FFFFFF; color: #000000} pre { color: #000000; background: #FFFFFF; font-family: courier; } .c { color: #228B22;} /* comment */ .cm { color: #000000;} /* comma */ .co { color: #000000;} /* colon */ .h { color: #CD5555; font-weight:bold;} /* here-doc-target */ .hh { color: #CD5555; font-style:italic;} /* here-doc-text */ .i { color: #00688B;} /* identifier */ .j { color: #CD5555; font-weight:bold;} /* label */ .k { color: #8B008B; font-weight:bold;} /* keyword */ .m { color: #FF0000; font-weight:bold;} /* subroutine */ .n { color: #B452CD;} /* numeric */ .p { color: #000000;} /* paren */ .pd { color: #228B22; font-style:italic;} /* pod-text */ .pu { color: #000000;} /* punctuation */ .q { color: #CD5555;} /* quote */ .s { color: #000000;} /* structure */ .sc { color: #000000;} /* semicolon */ .v { color: #B452CD;} /* v-string */ .w { color: #000000;} /* bareword */ 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-Datei.pt-c { color: #228B22;} /* comment */ .pt-cm { color: #000000;} /* comma */ .pt-co { color: #000000;} /* colon */ .pt-h { color: #CD5555; font-weight:bold;} /* here-doc-target */ .pt-hh { color: #CD5555; font-style:italic;} /* here-doc-text */ .pt-i { color: #00688B;} /* identifier */ .pt-j { color: #CD5555; font-weight:bold;} /* label */ .pt-k { color: #8B008B; font-weight:bold;} /* keyword */ .pt-m { color: #FF0000; font-weight:bold;} /* subroutine */ .pt-n { color: #B452CD;} /* numeric */ .pt-p { color: #000000;} /* paren */ .pt-pd { color: #228B22; font-style:italic;} /* pod-text */ .pt-pu { color: #000000;} /* punctuation */ .pt-q { color: #CD5555;} /* quote */ .pt-s { color: #000000;} /* structure */ .pt-sc { color: #000000;} /* semicolon */ .pt-v { color: #B452CD;} /* v-string */ .pt-w { color: #000000;} /* bareword */ 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.020002 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 30 Einträge)
|
Kalender
SucheStatistikLetzter Artikel:
20.11.2019 09:34 137 Artikel insgesamt
AbonnierenLinks
|