# Perl - Formate

### Einführung

Eine einfache Möglichkeit, Protokolle oder Tabellen übersichtlich auszugeben, bieten sogenannte Formate. Dort können beispielsweise Spalten einer Tabelle definiert werden; jeweils mit Breite und Positionierung des Eintrags (rechts-, linksbündig oder zentriert). Außerdem kann ein Seitenkopf definiert werden, der bei Ausgaben, die sich über mehrere Seiten erstrecken, auf jeder einzelnen Seite vor den eigentlichen Daten ausgedruckt wird.

Um Daten formatiert auszugeben, muß der Befehl `write` (optional mit einem Filehandle) benutzt werden. Es können für jedes Filehandle unabhängig voneinander Formate definiert werden.

### Definition eines Formats

Das Schema einer Formatdefinition sieht wie folgt aus:

> `format` <Name> `=`
> <Musterzeile>
> <Variablenzeile>
> `.`

Im einfachsten Falle ist der Name eines Formats gleich dem Namen des Filehandles, für das das Format verwendet werden soll (Standardwert: `STDOUT`). Will man einer Formatdefiniton einen anderen Namen geben, so kann die entsprechende Zuordnung von Formatname und aktuellem Filehandle durch Setzen der Variablen $~ geschehen.

Um bei mehrseitigen Dokumenten jeweils automatisch einen Seitenkopf ausgeben zu lassen, kann ein spezielles Format hierfür definiert werden. Der Name wird gebildet durch das Anhängen von "`_TOP`" an das Filehandle (Standardwert: `STDOUT_TOP`). Alternativ dazu kann eine beliebiger Name durch Setzen von $^ verwendet werden. Ansonsten erfolgt die Definition vollkommen analog zu der eines normalen Formats.

Die Musterzeile enthält die Definitionen der einzelnen Felder, in die dann später die Werte der Variablen der darauffolgenden Zeile eingetragen werden. Es dürfen mehrere Muster- und Variablenzeilen angegeben werden; allerdings ist darauf zu achten, daß sie immer paarweise auftreten (jede Variablenliste "füllt" die darüberstehende Musterzeile).

Außerdem können noch überall Kommentarzeilen eingefügt werden, die mit einem '`#`' beginnen.

Die Definitionen von Formaten dürfen an beliebiger Stelle im Programmcode stehen (wie Unterprogramme).

### Musterzeile

Jede dieser Zeilen bestimmt Felder in der Ausgabe, in die dann Variablenwerte (festgelegt in der jeweils darauffolgenden Zeile) eingesetzt werden sollen.

Ein normales Feld besteht aus einem '`@`' gefolgt von null oder mehr Positionierungszeichen eines Typs:

'`<`' (linksbündig)
'`|`' (zentriert)
'`>`' (rechtsbündig)

Beispiel:

    #!/usr/local/bin/perl -w

    $a = 12;

    write;

    format STDOUT =
    #    eine Spalte, vierstellig, zentriert
    @|||
    $a
    .

     12

Eine mehrzeilige Ausgabe von Zeichenketten wird durch Felder bewerkstelligt, die mit einem '`^`' beginnen. Dabei wird dann dort, wo das Feld in der Formatdefinition zum ersten Mal erscheint, ein möglichst großer Teil des Ausgabestrings dargestellt. Beim zweiten Auftreten wird ggf. dann ein Teil des Restes dargestellt, usw. (Achtung: in der Zeichenkette wird dabei sukzessive der jeweils dargestellte Teil entfernt, d.h., der Wert der Stringvariablen ändert sich u.U. bei jedem `write`).

Beispiel:

    #!/usr/local/bin/perl -w

    $text = "Dies ist ein Beispiel dafuer, wie einem Format mehrzeilige ";
    $text .= "Texteintraege dargestellt werden koennen.";

    write;

    format STDOUT =
    #    bis zu drei Zeilen Text
    ^<<<<<<<<<<<<<<<<<<<<<<<<<<<<
    $text
    ^<<<<<<<<<<<<<<<<<<<<<<<<<<<<
    $text
    ^<<<<<<<<<<<<<<<<<<<<<<<< ...
    $text
    .

    Dies ist ein Beispiel dafuer,
    wie einem Format mehrzeilige
    Texteintraege dargestellt ...

Oft weiß man vorher nicht, wie lang der Text wird. Um unnötige Leerzeilen zu vermeiden, setzt man einfach in die entsprechende Musterzeile eine Tilde ('`~`'). Will man einen längeren Text auf jeden Fall komplett ausgeben, so kann man dies durch zwei aufeinanderfolgende Tilden ('`~~`') in einer Musterzeile erreichen. In diesem Falle wird die Ausgabe dieser Zeile so oft wiederholt bis die Zeichenkette in der dazugehörenden Stringvariable vollständig dargestellt ist. Schließlich kann ein Text in seiner natürlichen Zeilenaufteilung in ganzer Länge ausgegeben werden, indem der Stringvariablen in der Musterzeile das Feld '`@*`' zugeordnet wird.

Eine besondere Art der Positionierung bietet das '`#`'. Nach einem '`@`' bewirkt es eine rechtsbündige Darstellung, wobei bei der Ausgabe einer Zahl ein optionaler Dezimalpunkt berücksichtigt wird. Nach einem '`^`' wird ein so markiertes Feld nur dann dargestellt, wenn die dazugehörende Variable definiert ist.

Beispiel:

    #!/usr/local/bin/perl -w

    $a = 117.127;
    write;

    format STDOUT =
    Betrag: @###.## DM (^###)
    $a, $b
    .

    Betrag:  117.13 DM (    )

### Variablenzeile

Eine Zeile dieser Art legt fest, welche Variablenwerte in die jeweils vorangegangene Musterzeile eingetragen werden sollen.

Dies kann einfach durch eine durch Kommata getrennte Liste sein; aber es ist auch möglich, Arrays (die mehrere Felder der Musterzeile abdecken) oder gar ganze Ausdrücke anzugeben, die dann beim Aufruf des Formats (via `write`) abgearbeitet werden. Die Variablenliste kann über mehrere Zeilen ausgedehnt werden, indem geschweifte Klammern ('`{...}`') verwendet werden.

Beispiel:

    #!/usr/local/bin/perl -w

    @datum = (6,1,1997);

    $a = 12;

    write;

    format STDOUT =
    #    Datumsdarstellung
    Datum: @>.@>.@>>>
    @datum
    #   Potenzen von $a
    @>>>> @>>>> @>>>>
    {
       $a,
       $a*$a,
       $a*$a*$a
    }
    .

    Datum:  6. 1.1997
       12   144  1728

### Spezielle Variablen

(In Klammern stehen jeweils die Namen, die alternativ verwendet werden können, wenn `use English;` benutzt wird.)

- `$~` (`$FORMAT_NAME`)

  Name des aktuellen Formats

- `$^` (`$FORMAT_TOP_NAME`)

  Name des aktuellen Seitenkopfes

- `$%` (`$FORMAT_PAGE_NUMBER`)

  Aktuelle Seitenzahl

- `$=` (`$FORMAT_LINES_PER_PAGE`)

  Anzahl der Zeilen pro Seite

- `$-` (`$FORMAT_LINES_LEFT`)

  Anzahl der restlichen Zeilen auf der aktuellen Seite

- `$^L` (`$FORMAT_FORMFEED`)

  Zeichenkette, die vor jedem Seitenkopf ausgegeben wird (z.B. Seitenvorschub auf einem Drucker).

- `$:` (`$FORMAT_LINE_BREAK_CHARACTERS`)

  Liste von Zeichen, an deren Stelle in einem String dieser getrennt werden darf (zur Aufsplittung bei Ausgabe von längeren Texten über mehrere Zeilen)

Die meisten dieser Variablen beziehen sich auf ein bestimmtes Filehandle. Um also darauf zuzugreifen, muß daher zunächst das aktuelle Filehandle mittels `select()` geändert werden. Einfacher und übersichtlicher ist dagegen die Verwendung des entsprechenden Standard-Moduls ("`use FileHandle;`").

Autor: Eike Grote | Letzte Änderung: 03.11.2004