Vorlage DokumentationRegulaereAusdruecke
Allgemeines
   Aufruf
   Einleitung
   Installation
   Konfiguration
   Syntax
Einführung
   MetabefehlsAusdruecke
   MetabefehlsSyntax
   RegulaereAusdruecke
   VordefinierteVariablen
Funktionen
   abs()
   after()
   and()
   antoi()
   before()
   ceil()
   change()
   close()
   crop()
   equals()
   exp()
   flatten()
   float()
   floor()
   int()
   isnothing()
   itoan()
   length()
   log()
   log10()
   match()
   not()
   open()
   or()
   random()
   read()
   readline()
   sign()
   status()
   statustext()
   substr()
   system()
   time()
   tolower()
   toupper()
   typeof()
   write()
   writeline()
   xname()
   xor()
Metabefehle
   #after
   #array
   #break
   #call
   #config
   #const
   #debug
   #default
   #dict
   #else
   #every
   #forever
   #func
   #if
   #ifregion
   #ifunit
   #include
   #input
   #message
   #next
   #notrace
   #proc
   #return
   #sort
   #table
   #tag
   #trace
   #var
   #while
Rückruf-Prozeduren
   CalcUnitCapacities
   CreateRegionHeader
   CreateUnitHeader
   EndRegion
   EndUnit
   OnBuilding
   OnExit
   OnInit
   OnRegion
   OnShip
   OnUnit
   OutputLineFilter
Report-Objekte
   building
   grenze
   partei
   preise
   races
   region
   report
   ship
   things
   unit
Anhang
   Danksagungen
   SkriptDebugger
   VorlageFAQ

Reguläre Ausdrücke

Einführung in reguläre Ausdrücke

Ein regulärer Ausdruck ist ein Muster, das auf eine Zeichenkette von links nach rechts angewendet wird. Die meisten Zeichen in dem Ausdruck stehen dabei für sich selbst und werden mit den Zeichen des zu durchsuchenden Textes verglichen. So passt das Muster

kleiner dicker Zwerg

auf einen dazu identischen Abschnitt des zu durchsuchenden Textes. Die Stärke regulärer Ausdrücke ist jedoch die Möglichkeit Alternativen und Wiederholungen ins Muster einzufügen. Diese werden durch sogenannte Meta-Zeichen dargestellt, welche nicht für sich selbst stehen, sondern auf besondere Weise ausgewertet werden.

Es gibt oft Fälle, in denen man aber nicht ein Muster fester Länge sucht, sondern eines, welches nur eine bestimmte Struktur erfüllt. Will man z.B. eine Zeichenkette finden die mit 'b' startet und durch eine Anzahl 'a' fortgesetzt werden, so kommen sogenannte Quantifier ins Spiel. Dabei handelt es sich um Zeichen (oder Kombinationen davon) die eine Wiederholung des vorangehenden Zeichens oder Teilmusters erlauben. Für das Beispiel wären dies:

ba* 'b' gefolgt von 0 bis bel. vielen 'a'
ba+ 'b' gefolgt von 1 bis bel. vielen 'a'
ba? 'b' gefolgt von einem optionalen 'a'
ba{3,} 'b' gefolgt von min. 3 'a'
ba{,5} 'b' gefolgt von max. 5 'a'
ba{3,5} 'b' gefolgt von 3 bis 5 'a'

Um aber sinnvollere Muster zu erzeugen braucht man zum Beispiel oft Alternativen. Die werden durch den senkrechten Strich getrennt, so steht also das Muster

Zwerg|Elf

für Zwerg oder Elf. Soll nur ein Teil des Musters aus Alternativen bestehen, so klammert man den Abschnitt. Als Erweiterung zu unserem ersten Muster kann man also z.B.

kleiner (dicker|bärtiger) Zwerg

verwenden um sowohl kleine dicke, als auch kleine bärtige Zwerge zu finden.

Die Quantifier können auch auf geklammerte Ausdrücke angewendet werden und bewirken dann eine wiederholte Anwendung des Musters innerhalb der Klammern, also könnte man zum Beispiel schreiben:

1(0|1)+0

Das ist ein Muster, das auf Zahlen zutrifft die mit 1 beginnen, dann ein bis bel. viele Einsen und Nullen enthalten und durch eine 0 beendet werden.

Will man aber z.B. auf Einheitennummern in Base 36 ein Muster definieren, so wäre es sehr mühsam alle 36 Zeichen als Alternativen aufzuführen. Darum gibt es die Zeichenklassen. Dabei handelt es sich um eine Möglichkeit Zeichenmengen zu definieren, aus denen dann die Alternaiven gewählt werden. So ist z.B.

0|1|2|3|4|5|6|7|8|9

identisch mit der Zeichenklasse

[0123456789]

Beide Ausdrücke stehen also für eine Ziffer von 0-9. Aber es gibt noch eine wesentliche Möglichkeit zur Vereinfachung. Innerhalb von Zeichenklassen sind nämlich Intervalle erlaubt. So kann man für die Ziffern auch schreiben:

[0-9]

Eine gültige Base36-Ziffer wäre also durch die Klasse

[0-9a-zA-Z]

definiert. Dabei wurde hier Groß- und Kleinschreibung aufgenommen.

So wäre also eine gültige Einheitennummer bei Eressea zur Zeit:

[0-9a-zA-Z]{1,4}

also min. 1 und max. 4 Base36-Ziffern.

Innerhalb von Zeichenklassen können noch weitere Vereinfachungen durch Sonderzeichen erreicht werden. Folgende Sequenzen stehen zur Verfügung:

\d eine bel. Dezimalziffer
\D ein bel. Zeichen das keine Dezimalziffer ist
\s ein bel. Whitespace-Zeichen, also Leerzeichen, Tabulatoren, Zeilenumbrüche, etc.
\S ein bel. Zeichen das kein Whitespace ist
\w ein bel. Wortzeichen (Buchstabe, Ziffer oder Unterstrich), jedoch keine Umlaute und kein 'ß'
\W ein bel. Nicht-Wortzeichen

ALERT! ACHTUNG: Es ist zu beachten, dass auch in Vorlage und Eressea ja der Backslash benutzt wird um Zeichenfunktionen aufzuheben. Daher müssen in regulären Ausdrücken in Textkonstanten alle Backslashes durch zwei Backslashes eingegeben werden. Aus [\d\w] wird also [\\d\\w] und will man einen Backslash in einem Ausdruck als Zeichen für sich selber verwenden, muss man, da er ja auch selber escaped, also seiner normalen Funktion beraubt werden muss, vier Backslashes benutzen. Will man z.B. nach der Zeichenkette \n suchen, also aus den beiden Zeichen Backslash und 'n' bestehend, und nicht die Zeilenende-Sequenz, z.B. um diese Folge in externen Dateien zu ermöglichen, so lautet der reguläre Ausdruck dafür \\n weil der Backslash für den Ausdruck entwerten muss, der Vorlage-String für den Ausdruck ist aber '\\\\n' weil die beiden Backslashes des regulären Ausdrucks ihrerseits in Vorlage-Strings entwertet werden müssen. Das ist nicht immer einfach, aber ein Problem das auch reguläre Ausdrücke in Sprachen wie C, C++ oder Java haben wenn sie sich an Perl orientieren.

Wird dieses Wissen umgesetzt, so wird also aus unserem Muster für Base36-Zahlen in einem Vorlage-String:

'[\\da-zA-Z]{1,4}]'

Wir haben kein \w verwendet, weil da ja auch noch mindestens ein anderes Zeichen (Unterstrich) drin ist.

Will man zum Beispiel alle Zeichen außer Ziffern und Buchstaben haben, kann man mit der Negation arbeiten:

[^0-9a-zA-Z]

Das '^' zu Beginn einer Zeichenklasse bedeutet, dass diese komplett negiert wird. Es hat nur am Anfang der Zeichenklasse diese Bedeutung und kann an jeder anderen Stelle für sich selbst stehen.

Unterschiede zu Perl

Die hier genannten Unterschiede beziehen sich auf den Stand von Perl 5.005.

  • Normalerweise ist ein Whitespace-Zeichen, da isspace() der ANSI-C-Bibliothek verwendet wird, ein Zeichen, das keine sichtbare Darstellung hat. Dies sind hier Leerzeichen, Zeilenvorschub, Zeilenumbruch, horizontaler Tabulatur und vertikaler Tabulator. Mit Perl 5 gilt der vertikale Tabulator nicht mehr als Whitespace.

  • Wiederholungsangaben können für Lookahead-Bedingungen nicht benutzt werden. In Perl ist das zwar erlaubt, führt aber nicht zu einem erwarteten Ergebnis. So stellt z.B. (?!a){3} nicht etwa sicher, dass die folgenden drei Zeichen kein 'a' sind, sondern es wird dreimal überprüft dass das nächste Zeichen kein 'a' ist.

  • Unterausdrücke die innerhalb von negativen Lookahead-Bedingungen vorkommen, werden zwar mitgezählt, aber ihr Inhalt wird nie gesetzt. Perl hingegen setzt die Werte, wenn die Bedingung nicht zutraf, aber nur wenn die negative Lookahead-Bedingung nicht verzweigt.

  • Die binäre Null ist in Suchmustern nicht erlaubt.

  • Die Escape-Sequenzen \l, \u, \L, \U, \E und \Q werden nicht unterstützt. Diese sind auch in Perl Teil der normalen Zeichenkettenbehandlung und nicht der regulären Ausdrücke.

  • Die Bedingung \G wird nicht unterstützt.

  • Die Konstruktionen (?{code}) und (?p{code}) werden nicht unterstützt, da ja kein Perl zur Verfügung steht.
Revision 03 Jan 2006

Page design, graphics and contents (c) copyright 1999-2004
by S.Schümann and contributing authors