Startseite --> Hilfen & Technische Artikel --> Codeschnipsel --> Perl: Einfacher Parser für Konfigurationsdateien
Wenn man ein komplexes Script programmiert, kann es durchaus nützlich sein, Konfigurationsvariablen in eine externe Datei auszulagern, damit es etwas übersichtlicher wird. Da Konfigurationseinstellungen allerdings auch häfig durch Nicht-Programmierer verändert werden müssen, macht es Sinn, diese in eine Datei auszulagern, die einfacher aufgebaut ist als ein Script und nicht irgendwelche für Programmiersprachen typische Eigenschaften aufweist (Dollar-Zeichen für Variablen, Semikolon am Ende einer Anweisung).
Der folgende (sehr) einfache Parser ist im Rahmen des Dev-Editor-Projektes entstanden (der Dev-Editor verwendet mittlerweile einen erweiterten Parser, der auch mit den aus Windows-INI-Dateien bekannten Sektionen umgehen kann). Er erlaubt es, Konfigurationsdateien einzulesen, die aus Schlüssel-Werte-Paaren bestehen, die wiederrum durch ein Gleichheitszeichen voneinander getrennt sind. Kommentare sind ebenfalls möglich: Zeilen, die mit einem #-Zeichen beginnen (vor diesem Zeichen dürfen beliebig viele Leerzeichen stehen), werden ignoriert.
sub parse_config($)
{
my $file = shift;
local *CF;
open(CF,'<'.$file) or die "Open $file: $!";
read(CF, my $data, -s $file);
close(CF);
my @lines = split(/\015\012|\012|\015/,$data);
my $config = {};
my $count = 0;
foreach my $line(@lines)
{
$count++;
next if($line =~ /^\s*#/);
next if($line !~ /^\s*\S+\s*=.*$/);
my ($key,$value) = split(/=/,$line,2);
# Remove whitespaces at the beginning and at the end
$key =~ s/^\s+//g;
$key =~ s/\s+$//g;
$value =~ s/^\s+//g;
$value =~ s/\s+$//g;
die "Configuration option '$key' defined twice in line $count of configuration file '$file'" if($config->{$key});
$config->{$key} = $value;
}
return $config;
}
Zunächst wird die als Funktionsparameter angegebene Datei zum Lesen geöffnet, der komplette Inhalt in die Variable $data eingelesen und die Datei anschließend wieder geschlossen. Der in $data gespeicherte Dateiinhalt wird nun zeilenweise aufgeteilt, die Zeilen werden in @lines gespeichert. Dann wird eine leere Hash-Referenz mit dem Namen $config angelegt, die später die einzelnen Konfigurationsoptionen beinhalten wird. Außerdem wird eine Variable namens $count angelegt und erhält den Wert 0. Diese Variable ist für das eigentliche Parsen der Konfigurationsdatei eher unwichtig, sie enthält lediglich die aktuelle Zeilennummer, die dann in Fehlermeldungen mit ausgegeben wird.
Jetzt beginnt das eigentliche Parsen der Datei. Die einzelnen Zeilen werden in einer foreach-Schleife folgendermaßen abgearbeitet:
Zunächst wird einmal die Variable $count um 1 erhöht. Dann wird die aktuelle Zeile daraufhin überprüft, ob sie nicht eine Kommentarzeile ist und ob sie den Anforderungen entspricht (s.o.). Sollte sie eine Kommentarzeile sein oder nicht den Anforderungen entsprechen, geht es mit Hilfe von next in den nächsten Schleifendurchlauf, sprich in die nächste Zeile.
Die Zeile wird nun mit split() am Gleichheitszeichen aufgetrennt, es werden aber nur zwei Elemente erzeugt, so dass Gleichheitszeichen in den Werten vorkommen können. Anschließend werden an Anfang und Ende von Schlüssel und Wert evtl. vorhandene Leerzeichen entfernt.
Nun wird überprüft, ob in der Hash-Referenz $config schon einmal ein Wert mit dem aktuellen Schlüsselnamen abgespeichert wurde. Ist dies der Fall, wird das Script mit einer Fehlermeldung, die den Schlüsselnamen und die aktuelle Zeilennummer enthält, abgebrochen. Ist dies nicht der Fall, werden Schlüssel und Wert in der Hash-Referenz gespeichert und es wird die nächste Zeile geparst.
Wenn alle Zeilen abgearbeitet sind, wird die Hash-Referenz zurückgegeben.
Wenn Sie diese Funktion in ein Modul auslagern möchten, empfehle ich, die croak()-Funktion aus dem Carp-Modul einzubinden (use Carp qw(croak);) und alle Aufrufe von die() durch croak() zu ersetzen.
Startseite --> Hilfen & Technische Artikel --> Codeschnipsel --> Perl: Einfacher Parser für Konfigurationsdateien