




  Auch als guter (!) Programmierer müssen Sie damit rechnen, dass Ihre Programme - 
und seien sie noch so kurz - Fehler aufweisen. Einige davon sind einfacher Art - 
Syntaxfehler, Endlosschleifen oder Beanstandungen (Option -w). Andere hingegen 
sind versteckt und liefern unverständliche oder gar keine Ergebnisse.
  Ein Weg, herauszufinden, was sich an jeder Stelle in Ihrem Skript abspielt, führt über 
print-Anweisungen. Mit Hilfe von print-Anweisungen können Sie die aktuellen 
Werte der Variablen kontrollieren und feststellen, ob Schleifen und Bedingungen auch 
ausgeführt werden. Es gibt jedoch noch einen anderen Weg, der besonders für 
längere Skripts empfehlenswert ist. Perl verfügt über einen Quellcode-Debugger, mit 
dem Sie die Ausführung eines Skripts schrittweise verfolgen und die verschiedenen 
Werte der Variablen während der Ausführung des Skripts ausgeben lassen können. 
Mit dem Debugger können Sie die Fehler in Ihrem Code schneller finden als mit 
print-Anweisungen.
In diesem Kapitel zeige ich Ihnen, wie Sie den Perl-Debugger einsetzen. Im einzelnen sehen Sie anhand eines kurzen Beispiels, wie Sie den Debugger normalerweise verwenden
Die Arbeitsweise des Perl-Debuggers läßt sich wahrscheinlich am besten anhand eines kleinen typischen Beispiels demonstrieren. Dazu gehen wir schrittweise durch die Ausführung eines einfachen Skripts mit Subroutinen, in diesem Falle das Namensskript aus Kapitel 6, »Bedingungen und Schleifen«, das eine Liste von Namen einliest, Sie bittet einen Suchbegriff einzugeben und die Namen zurückgibt, die dem Suchbegriff entsprechen.
Wenn Sie ein Skript bei eingeschaltetem Perl-Debugger ausführen, landen Sie direkt im Debugger und erhalten in etwa folgende Zeilen:
% perl -d statsfunk.pl statsdaten.txt
Loading DB routines from perl5db.pl version 1.01
Emacs support available.
Enter h or 'h h' for help.
main::(statsfunk.pl:3): &initvars();
DB<1>

Wenn Sie noch nicht wissen sollten, wie Sie den Debugger starten, zerbrechen Sie sich darüber nicht den Kopf. Ich werde gleich nach diesem kleinen Exkurs darauf eingehen.
  Die Schlußzeile DB<1> ist die Eingabeaufforderung des Debuggers. Hier geben Sie Ihre 
Befehle ein. Die Zahl 1 besagt, dass dies der erste Befehl ist. Befehle lassen sich durch 
Eingabe der Befehlsnummer wiederholen.
Die Zeile vor der Eingabeaufforderung gibt die aktuelle Codezeile an, die Perl anschließend ausführt. Der Teil zur Linken bezieht sich auf das aktuelle Paket, den Namen der Datei und die Zeilennummer. Der Teil zur Rechten ist die eigentliche Codezeile einschließlich der Kommentare zu der Zeile.
  Um eine Codezeile auszuführen, können Sie den Befehl n oder den Befehl s 
verwenden. Der s-Befehl geht etwas mehr in die Tiefe, da damit auch Subroutinen 
ausgeführt werden. Mit dem n-Befehl bleiben Sie bei der schrittweisen Ausführung auf 
der obersten Ebene Ihres Skripts. Subroutinen werden im Hintergrund abgearbeitet. 
Beide Befehle lassen sich wiederholen, indem man bei jeder Eingabeaufforderung die 
Eingabe-taste betätigt:
main::(statsfunk.pl:3): &initvars();
DB<1> s
main::initvars(statsfunk.pl:8): $input = "";
DB<1>
main::initvars(statsfunk.pl:9): @nums = ();
DB<1>
main::initvars(statsfunk.pl:10): %freq = ();
DB<1>
  In diesem Beispiel fällt auf, dass, sobald die Ausführung des Skripts in die 
&initvars()-Subroutine verzweigt (erfolgt in unserem Beispiel gleich in der ersten 
Zeile), die Informationen auf der linken Seite der Ausgabe den Namen dieser 
Subroutine widerspiegeln. So wissen Sie jederzeit, wo im Skript Sie sich befinden. 
Falls Sie aber die Übersicht verloren haben oder anhand der einzelnen Zeile Ihre 
Position im Skript nicht festlegen können,  ist es möglich mit Hilfe des Befehls l (steht 
für list) weitere Codezeilen anzeigen zu lassen:
DB<1> l
10==> %freq = (); # Hash: Zahl-Haeufigkeit
11: $maxfreq = 0; # hoechste Haeufigkeit
12: $count = 0; # Anzahl Zahlen
13: $sum = 0; # Summe
14: $avg = 0; # Durchschnitt
15: $med = 0; # Median
16: @keys = (); # temp keys
17: $totalspace = 0; # gesamte Breite des Histogramms
18 }
19
  Mit l lassen sich die auf die aktuelle Zeile folgenden zehn Zeilen am Bildschirm 
ausgeben. Durch Eingabe eines Minuszeichens können Sie auch die zehn Zeilen vor 
der aktuellen Zeile sichtbar machen. Durch mehrmaliges Eingeben von l und - 
können Sie sich den Quellcode auflisten lassen, die folgenden Zeilen und 
zurückliegende. Beachten Sie jedoch, dass Sie damit lediglich die Zeilen anzeigen 
lassen und Ihre Codezeile im Kontext sehen können - der Code selbst wird damit 
nicht ausgeführt.
  Beim Durchschreiten des Codes können Sie die Werte aller Variablen - Skalare, 
Arrays, Hashes und so weiter - mit dem Befehl x ausgeben lassen. Im nächsten 
Beispiel hat die Subroutine &getinput() gerade eine Zeile aus der Eingabedatei 
eingelesen, diese Zeile in der Variablen $input abgelegt und anschließend das Zeichen 
für »Neue Zeile« aus dieser Zeile entfernt. Bei DB<5> wird der Wert von $index und die 
aktuellen Werte von @nums ausgegeben (die Array-Indizes stehen links und die 
eigentlichen Elemente rechts). Beachten Sie, dass die Codezeile (hier Zeile 23) 
angezeigt wird, bevor sie ausgeführt wird, so dass der Wert von $input noch nicht in 
@nums abgelegt ist.
main::getinput(statsfunk.pl:21):          while (defined ($input = <>)) {
  DB<5> s
main::getinput(statsfunk.pl:22):              chomp ($input);
  DB<5>
main::getinput(statsfunk.pl:23):              $nums[$count] = $input;
  DB<5> x input
0  5
DB<6> x @nums
0  1
1  4
2  3
3  4
DB<7>
  Mit dem x-Befehl können Sie auch, wie im folgenden Beispiel zu sehen, Perl-Code 
ausführen, um die Anzahl der Elemente in @raw zu ermitteln oder das erste Element 
anzuzeigen:
DB<3> x scalar(@nums)
0 4
DB<4> x $raw[0]
0 1
  Wenn Sie Ihr Skript mit s oder n debuggen, wird Ihnen jede Zeile bis ins kleinste 
Detail angezeigt - manchmal sogar ausführlicher, als Sie es benötigen. Innerhalb einer 
Subroutine können Sie mit dem Befehl r das schrittweise Debuggen der Subroutine 
aufheben, den Rest der Subroutine ausführen und dann dorthin zurückkehren, von wo 
die Subroutine aufgerufen wurde. Dies kann bei verschachtelten Subroutinen 
wiederum eine Subroutine sein.
  Sie können mit der Eingabe von c den Debug-Prozess jederzeit abbrechen. 
Anschließend führt Perl den Rest des Skripts ohne weitere Unterbrechungen aus (es 
sei denn, Sie haben explizit Haltepunkte in Ihrem Skript aufgenommen, um zum 
Beispiel eine Eingabe einzulesen.)
  Zusätzlich zu der Möglichkeit, die Ausführung Ihres Skripts zeilenweise zu verfolgen, 
können Sie die Ausführung mit Haltepunkten steuern. Unter einem Haltepunkt 
versteht man eine Markierung in einer Codezeile oder zu Beginn einer Subroutine. Mit 
dem Befehl c wird das Skript bis zu einem gesetzten Haltepunkt ausgeführt und dort 
unterbrochen. Am Haltepunkt können Sie dann mit n oder s den Code zeilenweise 
durchgehen, mit x die Variablen ausgeben oder mit c den nächsten Haltepunkt 
ansteuern.
  Betrachten wir beispielsweise das Skript statsmenue.p1, mit dem wir gestern das 
stats-Skript in mehrere Subroutinen unterteilt haben. Die Subroutine &countsum() 
gibt die Anzahl und die Summe der Daten aus. Um die Summe zu berechnen, ruft sie 
die Subroutine &sumnums()auf. Sie setzen einen Haltepunkt bei der Subroutine 
&sumnums(), indem Sie den Befehl b gefolgt von dem Namen der Subroutine 
eingeben. Dann führen Sie mit c das Skript bis zu diesem Haltepunkt aus.
# perl -d statsmenue.pl statsdaten.txt
Loading DB routines from perl5db.pl version 1.01
Emacs support available.
Enter h or 'h h' for help.
main::(statsmenue.pl:3): @nums = (); # array of numbers;
DB<1> b sumnums
DB<2> c
Was moechten Sie ausgeben? (Beenden mit Q):
1. eine Liste der Zahlen
2. die Anzahl und Summe der Zahlen
3. die kleinste und die groesste Zahl
4. den Durchschnitts- und den Medianwert
5. ein Diagramm, wie oft jede Zahl vorkommt
Ihre Auswahl --> 2
Anzahl der Zahlen: 70
main::sumnums (statsmenue.pl:72): my $sum = 0;
DB<2>
  Und wie, meinen Sie, sollen Sie sich die Namen all Ihrer Subroutinen merken? Kein 
Problem. Mit der Eingabe von S können Sie alle verfügbaren Subroutinen ausgeben 
lassen. Insbesondere S main wird die von Ihnen definierten Subroutinen anzeigen 
(wundern Sie sich jedoch nicht, wenn auch hier einige zusätzliche Perl-Routinen 
auftauchen). Betrachten Sie das folgende Beispiel:
DB<7> S main
main::BEGIN
main::countsum
main::getinput
main::maxmin
main::meanmed
main::printdata
main::printhist
main::printmenu
main::sumnums
DB<8>

Der
main-Teil heißt so in Anlehnung an dasmain-Paket, in dem sich all Ihre Variablen und Subroutinen standardmäßig befinden. Auf Pakete werden wir im folgenden Kapitel 13 noch näher eingehen.
  Wenn Sie einen Haltepunkt in einer bestimmten Zeile setzen wollen, können Sie mit l 
das Skript listenförmig ausgeben, um die Zeile zu ermitteln, und dann diese 
Zeilennummer zusammen mit dem Befehl b verwenden:
DB<3> l
43: print "5. ein Diagramm, wie oft jede Zahl vorkommt.\n";
44: while () {
45: print "\nIhre Auswahl --> ";
46: chomp($in = <STDIN>);
47: if ($in =~ /^\d$/ || $in =~ /^q$/i) {
48: return $in;
49 } else {
50: print "Ungueltige Eingabe. 1-5 oder Q, bitte.\n";
51 }
DB<3>
  Beachtenswert ist auch, dass der Debugger die Ausführung des Skripts zur Laufzeit 
verfolgen kann. Mit den Befehlen n und s können Sie zwar jede Anweisung einzeln 
ausführen lassen, aber manchmal möchte man die Zeilen nicht einzeln durchgehen, 
sondern sich trotzdem die einzelnen Anweisungen bei der Ausführung ausgeben 
lassen. Der Befehl t schaltet die Verfolgung ein und aus. Wir verfolgen hier die 
Subroutine &printdata(), wobei ein Haltepunkt an die Spitze der foreach-Schleife 
gesetzt wurde:
DB<1> b 59
DB<2> t
Trace = on
DB<2> c
Was moechten Sie ausgeben? (Beenden mit Q):
1. eine Liste der Zahlen
2. die Anzahl und Summe der Zahlen
3. die kleinste und die groesste Zahl
4. den Durchschnitts- und den Medianwert
5. ein Diagramm, wie oft jede Zahl vorkommt
Ihre Auswahl --> 1
die Zahlen:
1 main::printdata(statsmenue.pl:59): foreach $num (@nums) {
DB<2> c
main::printdata(statsmenue.pl:60): print "$num ";
1 main::printdata(statsmenue.pl:61): if ($i == 10) {
main::printdata(statsmenue.pl:64): } else { $i++; }
main::printdata(statsmenue.pl:59): foreach $num (@nums) {
DB<2>
  An diesem Beispiel möchte ich Ihnen zeigen, dass bei der Verfolgung nicht nur die 
Ausgabe des Skripts angezeigt (man beachte die 1 am Zeilenanfang in der Mitte der 
Ausgabe direkt nach dem Befehl c), sondern auch jede Skriptzeile ausgegeben wird. 
Würden wir hier erneut c eingeben, würde die foreach-Schleife erneut durchlaufen, 
und wir erhielten die gleiche Ausgabe.
  Verlassen wird der Debugger mit q (einfach nur q).
DB<18> q
%
Soweit - so gut. Nach diesem Exkurs sollten Sie eine ungefähre Vorstellung davon haben, wie der Debugger funktioniert. Der Rest dieses Kapitels ist den Details der spezielleren Befehle gewidmet.
  Der für Perl mitgelieferte Debugger wird von der Befehlszeile aus mit der Option -d 
gestartet. Während Sie Ihre Perl-Skript unter Unix oder Windows NT lediglich durch 
Angabe des Skriptnamens aufgerufen haben, so müssen Sie zum Debuggen Perl 
explizit aufrufen, gefolgt von dem Skriptnamen und den Argumenten. Wenn Sie also 
normalerweise ein Skript wie folgt aufrufen:
% meinSkript.pl namen.txt
lautet der Aufruf für den Debugger wie folgt:
% perl -d meinSkript.pl namen.txt
  Wenn Sie der Meinung sind, dass Sie den Debugger recht häufig für ein bestimmtes 
ziemlich schwieriges Skript einsetzen werden, können Sie alternativ die Option -d 
auch in der  shebang-Zeile des Skripts aufnehmen.
#!/usr/bin/perl -wd

Vergessen Sie nicht, die Option wieder zu entfernen, sobald Sie mit dem Debuggen fertig sind.
Um den Debugger in MacPerl einzuschalten, wählen Sie im Script-Menü den Befehl Perl Debugger, speichern Sie Ihr Skript, und führen Sie es dann wie gewohnt aus. Wenn Sie vorhaben, Ihr Skript als Droplet zu verwenden (das Dateien als Eingabe akzeptiert), dann vergessen Sie nicht das Skript als Droplet zu speichern.
Beachten Sie, dass vor Aufruf Ihres Debuggers das Skript frei von Syntaxfehlern und Warnungen sein muss. Sie müssen diese fatalen Fehler beseitigen, bevor Sie Ihr Skript debuggen können. Da diese Aufgabe Ihnen ohnehin nicht erspart bliebe, sollte die Bürde nicht zu schwer sein.
  Während der Debugger läuft, können Sie jederzeit mit dem Befehl h Hilfe anfordern. 
Damit wird eine Liste der möglichen Befehle ausgegeben. Rollt Ihnen der Bildschirm 
zu schnell, steht Ihnen der Befehl |h zur Verfügung (pausiert nach jeder Seite). Hilfe 
gibt es auch zu jedem einzelnen Befehl (h plus Argument). Alle Befehle, die dem 
Argument entsprechen, werden dann wie folgt ausgegeben:
DB<3> h c
c [line|sub] Continue; optionally inserts a one-time-only breakpoint
at the specified position.
command Execute as a perl statement in current package.
DB<4>
  Jeder Debugger-Befehl hat eine bestimmte Nummer (im obigen Beispiel hatte der 
Befehl h c die Nummer 3). Mit einem Ausrufezeichen und der Befehlsnummer können 
Sie jederzeit auf einen der vorangegangenen Befehle Bezug nehmen.
DB<4> !3
  Einen Überblick über die letzten paar Befehle erhalten Sie mit H und einer Zahl, der 
ein Minuszeichen vorangestellt wurde:
DB<13> H -3
13: H-3
12: b sumnums
11: x @nums
DB<14>
  Sie verlassen den Debugger mit q. Ist die Ausführung Ihres Perl-Skripts abgeschlossen, 
können Sie mit R die Ausführung erneut starten. Beachten Sie, dass R je nach 
Umgebung und Befehlszeilenargumenten, die für das Skript verwendet wurden, nicht 
funktioniert.
Verfolgen bedeutet, dass Sie jede Zeile Ihres Skripts angezeigt bekommen, während sie von Perl ausgeführt wird. Wird eine Zeile dabei mehrmals hintereinander ausgeführt, wie zum Beispiel in einer Schleife, wird jeder Durchgang von Perl angezeigt. Bei sehr komplexen Skripten ist die Ausgabe deshalb oft umfangreicher als notwendig. Aber mit Haltepunkten an bestimmten Positionen mag es zeitweise recht nützlich sein, die genaue Reihenfolge der Ausführung des Skripts zu verfolgen.
  Um zwischen den Verfolgungsmodi in Ihrem Perl-Skript hin- und herzuschalten, steht 
Ihnen t zur Verfügung. Ist die Verfolgung ausgeschaltet, wird sie mit t eingeschaltet 
und umgekehrt. Die folgende Ausgabe zeigt zum Beispiel das Ergebnis einer 
ausgeführten Schleife mit ausgeschalteter und mit eingeschalteter Verfolgung (der 
Haltepunkt befindet sich in Zeile 59, einer foreach-Schleife).
main::printdata(statsmenue.pl:59):         foreach $num (@nums) {
  DB<4> c
2 main::printdata(statsmenue.pl:59):         foreach $num (@nums) {
  DB<4> t
Trace = on
  DB<4> c
main::printdata(statsmenue.pl:60):               print "$num ";
2 main::printdata(statsmenue.pl:61):             if ($i == 10) {
main::printdata(statsmenue.pl:64):               } else { $i++; }
main::printdata(statsmenue.pl:59):           foreach $num (@nums) {
  Bei eingeschalteter Verfolgung können Sie die Ausführung Ihres Skripts mitverfolgen. 
Eine Stapelverfolgung zeigt Ihnen, wo Sie bereits gewesen sind - im Falle von 
verschachtelten Subroutinen zeigt sie Ihnen die Subroutine, die die von Ihnen zur Zeit 
ausgeführte Subroutine aufgerufen hat, und alle, die eventuell noch darüber 
angeordnet sind - bis zur obersten Ebene Ihres Skripts. Die Stapelverfolgung wird mit 
dem Befehl T aktiviert:
DB<4> T
@ = main::sumnums() called from file 'statsmenue.pl' line 68
$ = main::countsum() called from file 'statsmenue.pl' line 13
DB<4>
  Die Zeichen zu Beginn dieser Zeilen geben den Kontext an, in dem die Subroutine 
aufgerufen wurde. So zeigt die erste Zeile dieser Stapelverfolgung, dass die Subroutine 
&sumnums() (die aktuelle Routine) in einem Listenkontext (angezeigt durch das @-
Zeichen am Zeilenanfang) von der Routine &countsum() aus aufgerufen wurde. Die 
Routine &countsum() wiederum wurde von dem main-Teil des Skripts in einem 
skalaren Kontext aufgerufen (angezeigt durch das $ am Zeilenanfang).
  Um den Code Ihres Skripts schrittweise zu durchwandern, müssen Sie einen der 
Befehle s oder n verwenden. Mit der Eingabetaste wiederholen Sie Ihre vorige 
Eingabe (s oder n). Bei jedem Schritt zeigt Perl die Codezeile an, die es als nächstes 
ausführen wird (nicht die aktuell ausgeführte Codezeile):
DB<1> s
main::getinput(statsmenue.pl:29): $nums[$count] = $_;
DB<1>
  Der Unterschied zwischen s und n liegt darin, dass der Befehl s bei der Überwachung 
in die Ausführung untergeordneter Subroutinen verzweigt, während n diese 
Subroutinen zwar ausführt, jedoch bei der schrittweisen Überwachung auf der 
gleichen Ebene bleibt.
  Um die Ausführung einer Subroutine in Einzelschritten abzubrechen, den Rest der 
aktuellen Subroutine auszuführen und zu der Anweisung zurückzukehren, die die 
Subroutine ursprünglich aufgerufen hat, verwenden Sie den Befehl r.
  Um die Einzelschrittausführung für den gesamten Code aufzuheben, verwenden Sie 
den Befehl c.
Sie können den aktuell ausgeführten Quelltext mit Zeilennummern ausgeben lassen, um sich den Kontext zu der aktuellen Codezeile anzeigen zu lassen oder um nach einer speziellen Zeile zu suchen, bei der ein Haltepunkt gesetzt werden soll.
  Die nächsten zehn Zeilen des Codes erscheinen bei Eingabe des Befehls l:
DB<15> l
79==> $sum += $num;
80 }
81: return $sum;
82 }
83
84 # kleinste und groesste Zahl ausgeben
85 sub maxmin {
86: print "Kleinste Zahl: $nums[0]\n";
87: print "Groesste Zahl: $nums[$#nums]\n\n";
88 }
DB<15>
  Weitere Aufrufe von l werden die jeweils folgenden zehn Zeilen anzeigen. Sie können 
l aber auch zusammen mit einer Zeilennummer verwenden, um genau diese Zeile 
anzuzeigen, oder mit einem Zeilenbereich (zum Beispiel 1-4), um speziell diese Zeilen 
auszugeben, oder mit dem Namen einer Subroutine, um die ersten zehn Zeilen dieser 
Subroutine aufzulisten.
  Um in der Anzeige einige Zeilen zurückzuwandern, gibt es den Befehl -. Wie schon bei 
dem Befehl l können Sie mit mehrmaliger Eingabe von - auch weiter 
zurückwandern.
  Mit dem Befehl w erhalten Sie einen Ausschnitt um die aktuelle Zeile (oder die 
spezifizierte Zeile, falls angegeben): Es werden einige Zeilen davor und einige Zeilen 
danach eingeblendet. Ein Pfeil (==>) markiert die aktuelle Zeilenposition:
DB<3> w
24 # Input aus Datei lesen und dann sortieren
25 sub getinput {
26: my $count = 0;
27==> while (<>) {
28: chomp;
29: $nums[$count] = $_;
30: $count++;
31: }
32: @nums = sort { $a <=> $b } @nums;
33: }
  Mit einem Mustervergleich suchen Sie nach einer bestimmten Zeile im Quelltext. /
daten/ wird zum Beispiel nach dem ersten Vorkommen des Wortes daten suchen. 
Mit ?muster? durchsuchen Sie die Datei rückwärts.
  Einen letzten nützlichen Befehl zum Auflisten möchte ich Ihnen noch vorstellen: S. 
Damit werden Ihnen alle Subroutinen, die im Skript auftauchen, angezeigt. Die 
meisten dieser Subroutinen sind Perl- oder Debugger-spezifisch. S zusammen mit 
einem Paketnamen (zum Beispiel main) wird jedoch nur die Subroutinen in dem Paket 
ausgeben:
DB<20> S main
main::BEGIN
main::get_muster
main::namen_lesen
main::suche_muster
Morgen werde ich Ihnen mehr zu den Paketen erzählen.
In dem Quelltext zu Ihrem Skript herumzublättern ist nicht nur schön und praktisch, es hilft Ihnen auch, herauszufinden, was in Perl abläuft, wenn Ihr Skript ausgeführt wird. Die folgenden Befehle dienen dazu, die Werte der Variablen auszugeben:
  X gibt alle Variablen in dem aktuellen Paket aus. Da viele dieser Variablen Perl-
spezifisch sind (einschließlich spezieller Variablen wie @_, $_ und $1), kann die Liste 
ziemlich lang werden. X zusammen mit dem Namen einer Variablen gibt alle Variablen 
aus, die mit dem Suchnamen übereinstimmen. Beachten Sie, dass Sie nur den Namen 
selbst angeben und nicht die Präfixe wie $, @ oder %. X foo gibt die Werte aller 
Variablen aus, deren Namen foo lautet ($foo, @foo und %foo).
  Der Befehl V wird verwendet wie X. Zusätzlich kann jedoch ein optionaler Paketname 
angegeben werden, um die Variablen dieses Pakets auszugeben. Diese Eigenschaft ist 
allerdings erst von Belang, wenn Sie mit Paketen arbeiten. Der Vollständigkeit halber 
möchte ich Sie hier jedoch erwähnen.
  Der Befehl X birgt das Problem, dass lokale Variablen innerhalb von Subroutinen 
offensichtlich nicht erkannt werden.  Um die Werte von lokalen Variablen auszugeben 
oder kleinere Perl-Fragmente auszuführen, an deren Ergebnis Sie interessiert sind, 
verwenden Sie den x-Befehl:
DB<3> x $input
0 'Dante Alighieri'
  Wenn Sie Arrays oder Hashes ausgeben, wird der Inhalt des Arrays oder des Hash 
angezeigt. Die Ausgabe von X und V ist etwas einfacher zu lesen als die von x, 
besonders im Falle von Hashes. Und so sieht ein Hash bei der Verwendung von X aus:
DB<4> X %names
%names = (
'Adams' => 'Douglas'
'Alexander' => 'Lloyd'
'Alighieri' => 'Dante'
'Asimov' => 'Isaac'
'Barker' => 'Clive'
'Bradbury' => 'Ray'
'Bronte' => 'Emily'
)
  Das Setzen von Haltepunkten innerhalb eines Skripts erlaubt es Ihnen, das Skript 
normal auszuführen und an bestimmten Punkten (in der Regel dort, wo alles anfängt, 
falsch zu laufen) anzuhalten. Sie können beliebig viele Haltepunkte in Ihrem Skript 
setzen und dann mit den Befehlen zur Einzelschrittausführung oder zur 
Variablenausgabe das Problem einkreisen. Nehmen Sie mit c die Ausführung des 
Codes nach dem Haltepunkt wieder auf.
  Sie setzen einen Haltepunkt mit dem Befehl b. Wird der Befehl ergänzt um den 
Namen einer Subroutine, befindet sich der Haltepunkt an der ersten Anweisung 
innerhalb dieser Subroutine. Der Befehl b zusammen mit einer Zeilennummer setzt 
den Haltepunkt in genau dieser Zeile. Ohne Argumente wird mit b ein Haltepunkt in 
der aktuellen Zeile gesetzt. Im Quellcode-Listing erscheinen Haltepunkte als ein 
kleingeschriebenes b (in unserem Beispiel in Zeile 33):
DB<19> w 33
30 }
31
32 sub suche_muster {
33:b my $key = $_[0];
34: my $gefunden = 0;
35: foreach $ln (sort keys %namen) {
36==> if ($ln =~ /$key/o || $namen{$ln} =~ /$key/o) {
37: print "$ln, $namen{$ln}\n";
38: $gefunden = 1;
39 }
  Der Befehl L dient dazu, alle Haltepunkte, die Sie gesetzt haben, auf einmal 
auszugeben:
DB<22> L
namessub.pl:
9: my @raw = (); # raw Liste von Namen
break if (1)
33: my $key = $_[0];
break if (1)
  Gelöscht wird ein Haltepunkt, indem die Zeilennummer oder der Subroutinenname 
zusammen mit dem Befehl d verwendet wird. Mit D werden alle gesetzten Haltepunkte 
auf einmal gelöscht.
DB<22> d 9
DB<23> L
namessub.pl:
33: my $key = $_[0];
break if (1)
  Bis jetzt habe ich Ihnen vornehmlich die Befehle vorgestellt, die Ihnen den Einstieg in 
die Arbeit mit dem Debugger erleichtern und die Sie wahrscheinlich am häufigsten 
anwenden. Neben den hier vorgestellten Befehlen können Sie mit Perl aber auch 
noch bedingte Haltepunkte setzen, den Wert der Variablen ändern, Aktionen in 
bestimmten Zeilen ausführen und mehr oder weniger komplette Perl-Skripts eingeben 
und deren Ausführung interaktiv verfolgen. Sobald Sie mit dem Perl-Debugger etwas 
vertrauter sind, werden Sie den Befehl h garantiert öfter verwenden und, wenn nötig, 
die perldebug-Manpage zu Rate ziehen.
  Der Debugger wird Ihnen helfen, Probleme in Ihrem Code zu lokalisieren. Die fleißige 
Verwendung der Option -w ermöglicht es, viele Probleme zu verhindern, bevor das 
Skript überhaupt gestartet wird (oder bevor man den Debugger überhaupt 
konsultieren muss, um herauszufinden, was falsch läuft). Machen Sie es sich also zur 
Gewohnheit, wann immer möglich, -w zu verwenden.
In diesem Kapitel habe ich Ihnen die wichtigsten Debugger-Befehle vorgestellt. Wenn Sie so richtig in die Arbeit mit dem Debugger einsteigen, sollten Sie in der perldebug- Manpage oder der Online-Hilfe nachschauen, welche weiteren Befehle und Optionen Ihnen zur Verfügung stehen.
  In Perl können Sie das Verhalten des Debuggers anpassen. Sie können aber auch ein 
ganz anderes Debugger-System verwenden. Der Schalter -d zusammen mit einem 
Doppelpunkt und dem Namen des Moduls bindet das Modul als neuen Debugger ein. 
So können Sie zum Beispiel mit dem Modul Devel::DProf von CPAN Laufzeitprofile 
Ihrer Perl-Skripten erstellen (testen, wie lange Ihre Subroutinen dauern, um 
herauszufinden, wo Ihr Code noch effizienter sein könnte). Sobald Sie das Modul 
installiert haben, können Sie es wie folgt aufrufen:
% perl -d:DProf dasSkript.pl
  Die Datei perl5db.pl enthält den Code für den Debugger. Sie können diese Datei 
kopieren und Ihren Ansprüchen gemäß modifizieren. Weitere Informationen finden 
Sie in der perldebug-Manpage  oder den Dokumentationen zu dem DProf-Modul.
Sie können den Debugger nutzen, um Perl in einer Art interaktivem Modus auszuführen. So können Sie Befehle testen und deren Ausgabe direkt verfolgen. Sie benötigen dafür nicht einmal ein richtiges Skript. Und so sieht ein einfacher Befehl aus, mit dem Sie den Debugger ohne ein Skript zum Debuggen laden:
% perl -d -e1

Um genau zu sein, Sie haben Perl damit ein Skript zur Ausführung übergeben. Dieses Skript ist jedoch nur ein Zeichen lang:
1. Mit der Option-ewerden Perl-Skripts direkt von der Befehlszeile ausgeführt. Dieses Thema schneiden wir noch einmal am Ende des Buches in Kapitel 20 an.
In den letzten zwei Wochen habe ich mich bemüht, Sie auf häufige Fehler hinzuweisen, die fast allen Perl-Anfängern (und auch erfahrenen Programmierern) immer wieder unterlaufen. In der perltraps-Manpage finden Sie ebenfalls eine Liste der häufigsten Fallen und darüber hinaus noch vieles mehr. Schon ein kurzes Studieren dieser Seite wird Ihnen viele interessante Hinweise liefern, wenn es darum geht, Probleme bei schwierigem Code zu lösen.
Die Perl-Dokumentation umfaßt außerdem einen umfangreichen Satz an FAQ- Dateien (häufig gestellte Fragen). Bevor Sie sich vor Verzweiflung über ein bestimmtes Problem die Haare raufen, sehen Sie lieber einmal in den FAQs nach. Beginnen Sie dabei mit der perlfaq-Manpage, und lassen Sie sich von dort aus leiten.
Heute haben wir zwar nicht besonders viel über Perl selbst erfahren, dafür aber um so mehr über den dazugehörigen Befehlszeilen-Debugger. Sie wissen jetzt, wie Sie den Debugger aufrufen und starten, wie Sie jede Zeile Ihres Skripts einzeln ausführen, den Quelltext ausgeben, Haltepunkte setzen, die Ausführung verfolgen und Informationen über verschiedene Teile Ihres Skripts während seiner Ausführung einholen.
  Mit dem Debugger gibt es nur wenige Probleme, die Ihnen verborgen bleiben. Es 
lassen sich Probleme damit schneller feststellen als mit print-Anweisungen.
Frage:
 Ich verwende emacs. Gibt es eine Möglichkeit, den Perl-Debugger zusammen mit 
emacs zu verwenden?
Antwort:
 Aber klar. In der Datei cperl-mode.el finden Sie massenweise Material 
darüber, wie man Perl in den emacs einbindet. Diese Datei gehört zum 
Standardumfang von Perl und befindet sich in dem Verzeichnis emacs.
Frage:
 Ich bin eher an Debugger mit grafischer Oberfläche gewöhnt. All diese Befehle 
auf Befehlszeilenebene nerven mich. Gibt es für Perl auch visuelle Debugger?
Antwort:
 Wenn Sie den ActiveState-Port von Perl für Windows verwenden, steht Ihnen 
über ActiveState ein phantastischer visueller Perl-Debugger zur Verfügung. 
Weitere Informationen finden Sie unter http://www.activestate.com.
Der Workshop enthält Quizfragen, die Ihnen helfen sollen, Ihr Wissen zu festigen, und Übungen, die Sie anregen sollen, das eben Gelernte umzusetzen und eigene Erfahrungen zu sammeln. Versuchen Sie, das Quiz und die Übungen zu beantworten und zu verstehen, bevor Sie zur Lektion des nächsten Tages übergehen.
-w oder 
print?
 X und V zum Ausgeben der Variablen?
Geben Sie folgendes Skript ein:
#!/usr/bin/perl -w
my @foo = (2,5,3,7,4,3,4,3,2,3,9);
foreach $wert (0..10) {
&multiplizieren($wert, $foo[$wert]);
}
sub multiplizieren {
my ($num, $val) = @_;
print "$num mal $val ist gleich ", $num * $val, "\n";
}
Lassen Sie den Debugger darüber laufen und führen Sie folgende Debugger- Operationen durch:
t die Verfolgung ein, und lassen Sie mit c die Ergebnisse 
anzeigen.
 R ein, um das Skript erneut auszuführen. Gehen Sie mit n schrittweise 
durch das Skript. Wenn Sie sich innerhalb der foreach-Schleife befinden, lassen 
Sie die Werte für $wert mehrmals ausgeben.
 R ein, um das Skript erneut auszuführen. Gehen Sie mit s schrittweise 
durch das Skript. Geben Sie innerhalb der Subroutine &multiplizieren() die 
Werte von $num und $val aus. Kehren Sie mit r wieder aus der Subroutine 
&multiplizieren() zurück.
 R ein, um das Skript erneut auszuführen. Setzen Sie mit dem Befehl b 
in der Subroutine &multiplizieren()einen Haltepunkt. Lassen Sie den 
Haltepunkt mit L anzeigen. Führen Sie mit c das Programm bis zum Haltepunkt 
aus. Löschen Sie mit d den Haltepunkt wieder.
 #!/usr/bin/perl -w
@foo = (2,5,3,7,4,3,4,3,2,9);
while ($i < $#foo) {
&multiplizieren($i, $foo[$i]);
}
sub multiplizieren {
my ($num, $val) = @_;
print "$num mal $val ist gleich ", $num * $val, "\n";
}
Hier die Antworten auf die Workshop-Fragen aus dem vorigen Abschnitt.
-w dient dazu, Syntaxfehler oder schlechten Programmierstil zu finden 
(oder zu vermeiden). Der Perl-Debugger unterstützt Sie bei allen anderen 
Problemen: wenn Arrays nicht eingerichtet oder ausgegeben werden, Werte nicht 
übereinstimmen oder die Ausführung des Skripts nicht der erstrebten Logik 
entspricht. Die gleiche Hilfestellung - allerdings in reduzierter Form - erhalten Sie 
mit der print-Anweisung, die jedoch mit mehr Aufwand verbunden ist und oft 
größere Schwierigkeiten hat, das Problem zu orten. Mit dem Debugger können 
Sie auch die Werte von Variablen ändern und beliebige Codefragmente 
ausführen, während das Skript gerade in Ausführung ist - all dies ist mit einer 
einfachen print-Anweisung nicht möglich.
 perl ein, gefolgt 
von der Option -d, dem Namen Ihres Skripts und etwaiger Skriptargumente. 
Wenn Sie mit MacPerl arbeiten, müssen Sie den Perl-Debugger über das Menü 
Script aufrufen.
 l allein zeigt die nachfolgenden Codezeilen an
   
 l zusammen mit einer Zeilennummer zeigt genau diese Zeile an
   
 l zusammen mit einem Zeilenbereich zeigt genau diesen Bereich an
   
 - bringt eine Reihe von voranstehenden Codezeilen zur Anzeige
   
 w zeigt einige Zeilen vor und einige Zeilen nach der aktuellen Zeile an
   
X gefolgt vom Variablennamen (ohne die Zeichen $, @ oder %) aus. Andere 
Variablen und die Ergebnisse von Perl-Ausdrücken (wie zum Beispiel 
$hash{'key'}) geben Sie mit dem Befehl x aus.
 n 
verwenden, überspringen Sie die Subroutinen. Diese werden zwar ausgeführt, 
aber ihr Inhalt wird nicht angezeigt.
 X gibt die Variablen für das aktuelle Paket (main) aus. Der Befehl V gibt 
Variablen in einem beliebigen gegebenen Paket aus (wenn Sie später mit Paketen 
arbeiten, wird Ihnen dieser Befehl noch sehr dienlich sein).
 $i wurde nicht initialisiert, so dass die Subroutine &multiplizieren() 
Initialisierungsfehler auslöst, wenn sie versucht, den Wert von $num 
auszugeben.
   
 $i wird nicht inkrementiert. Das bedeutet, dass i immer den Wert 0 behält 
und in einer Endlosschleife hängenbleibt.
   




