[Allegro] Vb.196 Preprint: Regulaere Ausdruecke

Bernhard Eversberg ev at biblio.tu-bs.de
Mo Dez 18 10:06:27 CET 2006


Verlautbarung 196 der Entw.Abt.                              2007-01-03
-------------------------------

                                     VORABDRUCK!
                                Noch unvollstaendig!
                  Neue Funktionen erst mit V27.0 im Jan.2007 verfuegbar
                                           =================

Regulaere Ausdruecke (engl. "regular expressions")
--------------------
Dieses Konzept ist jedem Programmierer bekannt, vor allem in den
Skriptsprachen Perl und Python, und in der UNIX-Welt ganz allgemein.
Weiter unten steht kurz beschrieben, wie solche Ausdruecke aussehen.
Im allegro-System wird die Verwendung von regulaeren Ausdruecken vor
allem fuer die Volltextsuche gewuenscht, aber auch allgemein als ein
maechtigeres Werkzeug zum Durchsuchen von Zeichenfolgen, das ueber
einen schlichten Byte-fuer-Byte-Vergleich hinausgeht.
Mit V27.0 wird schon ein neuer FLEX zur Volltextsuche bereitgestellt
werden, der schneller ist als der bisherige und der mit regulaeren
Ausdruecken arbeiten kann.

Hinweis fuer Kenner
Man verwendet ueblicherweise frei verfuegbare Unterprogramme, die man
im Netz leicht finden kann, auch fuer C++. Fuer "allegro" wurde die
kompakte Implementierung von Ozan S. Yigit gewaehlt:
http://www.cse.yorku.ca/~oz/regex.bun
Die Versionen von Perl und Python sind z.B. noch maechtiger, aber nicht
alles, was dort moeglich ist, waere im allegro-Kontext brauchbar.
Ein paar Modifikationen waren noetig, um den Besonderheiten von
allegro-Daten gerecht zu werden.


Neuer FLEX-Befehl srx - die Grundlage
-------------------------------------

srx <suchausdruck>

sucht in der iV nach dem <suchausdruck>, wobei dies ein
sog. "regulaerer Ausdruck" sein kann, im einfachen Fall ein
schlichtes Wort.
Mit  if yes  stellt man fest, dass der Ausdruck in der iV vorkommt.

Wenn hinter srx nichts steht, wird als Suchwort nicht der Inhalt
der iV benutzt (denn diese soll ja durchsucht werden!), sondern
die Variable #u!! . Man wuerde deshalb schreiben

var ...suchbegriff...
ins #u!!
var ... zu durchsuchender Text...
srx
if can mes;end    // formaler Fehler im Suchbegriff!

Dieses scheinbar umstaendliche Verfahren wurde gewaehlt, weil
man damit die hoechstmoegliche Flexibilitaet in der Anwendung hat.
Durchsucht wird also jeweils der Text in der iV. Deren maximale
Laenge ist 256K.
Beispiel: Feststellen, ob in der Textdatei abc.txt das Wort
"ViewListe" vorkommt. Dafuer genuegen 4 Zeilen:

      // zuerst den Suchbegriff in die Variable #u!! setzen
#u!! viewliste
var Fabc.txt         // Text der Datei abc.txt in die iV einlesen
srx                  // darin suchen nach Inhalt von #u!!
if yes mes gefunden!


Komplette Anwendung
-------------------
Der neue FLEX  ftr.flx  leistet eine Volltextsuche in der gesamten
Datenbank. Darin kann man das Verfahren studieren.
Tip: Wenn ein Suchbegriff mehrfach (u.U. sehr oft) zur Anwendung
kommt, kann man ihn vorher formal pruefen, damit das "if can"
nicht bei jeder Anwendung auszufuehren ist. Das geht so:
   var "abcd"
   srx
   if cancel mes;end
Mit "mes" wird dann die Fehlermeldung angezeigt. In Regulaeren
Ausdruecken kann man jede Menge formale Fehler machen ...

ftr.flx  nutzt einen weiteren neuen Befehl:
fetch r
Dieser holt einen ganzen Datensatz aus der Datendatei in die iV.
Er wird weiter unten genauer beschrieben.



Und so formuliert man regulaere Ausdruecke
------------------------------------------
Ein Ausdruck dieser Art muss bei der Anwendung in #u!! stehen, der
zu durchsuchende Text in der internen Variablen.
Die Punkte 2 und 3 sind allegro-spezifisch modifiziert, 1 gibt es
im gaengigen Standard nicht.

  1. Unterstrich an erster Position: Exaktheit
     _abc  oder  abc
     Exakte bzw. umcodierte Suche
     Setzt man einen _ vor den Suchbegriff, wird dieser exakt gesucht,
     d.h. mit Eingabe von  _Müll  findet man nur Müll, nicht Muell oder
     muell oder müll.
     Ohne _ wird der Datentext umcodiert, der Suchbegriff aber
     nicht! Man muss also  muell  eingeben, um Müll, Muell und
     muell und müll mit einer einzigen Suche zu finden.
     Man wird meistens umcodiert suchen wollen, deshalb fordert diese
     Variante kein Steuerzeichen. Wichtig: Dann nur Kleinbuchstaben
     ohne Akzente eingeben, Umlaute aufgeloest, ss statt ß!
     (Der _ hat nur in der ersten Position diese Wirkung.)
     Zur Umcodierung werden die p- oder q-Befehle in den Indexparametern
     verwendet, es wird aber noch weitere Alternativen geben.

  2. Zirkonflex auf erster Position: Feldanfang
     ^abc  findet  abc  nur, wenn es an einem Feldanfang steht.
     Dabei gilt der Anfang des Feldtextes, ohne die Kategorienummer.
     Also:  _^Shakesp  findet  #40 Shakespeare und #31 Shakespeare
     Wenn der zu durchsuchende Text (der iV-Inhalt) nicht mit '#'
     beginnt, gilt das erste Zeichen als Textanfang.

  3. Dollar an letzter Position: Feldende
     abc$  findet  abc  nur, wenn es am Ende eines Feldes steht.
     Wenn der zu durchsuchende Text (der iV-Inhalt) nicht mit '#'
     beginnt, gilt nur das Ende des gesamten Textes.

  4. Punkt ist Joker (engl. "wildcard")
     AB.D  findet jedes ABxD, mit beliebigem Zeichen x
     Mehrere Punkte innerhalb eines Suchbegriffs moeglich, jeder Punkt
     steht dann fuer genau ein Zeichen.

  5. Stern: Mehrfachvorkommnis
     ABc*D  findet ABD, ABcD, ABccD, ABcccD ... (d.h. c darf fehlen)

  6. Punkt-Stern: Binnentrunkierung (Kombination aus 4 und 5)
     AB.*CD  findet  ABxyzCD  mit beliebiger Folge xyz, aber im selben
        Datenfeld, nicht irgendwo weiter hinten im Datensatz!
        Das entspricht  AB,CD  im Programm SRCH

  7. Plus: wie Stern, aber mindestens ein Vorkommnis
     ABx+D  findet ABxD, ABxxD, ...  (d.h. mind. ein x muss vorkommen)

  8. Eckige Klammern: Variantensuche
     AB[pq]Z   findet  ABpZ und ABqZ
     AB[c-f]Z  findet  ABcZ, ABdZ, ABez, ABfZ
     Die Angabe [c-f] deutet also an, dass eines der Zeichen im
     Bereich c-f an der Stelle vorkommen muss.
     [^c-f] bedeutet Negation, d.h. Zeichen c-f sollen an der Stelle
     nicht auftreten
     Eine Angabe [c-fp-y] verlangt, dass ein Zeichen aus dem Bereich
     c-f oder p-y vorkommt.

  9. Kombinationen [...]* und  [...]+
     * und + koennen auch hinter ] auftreten und beziehen sich dann auf
     die in [...] angegebenen Zeichen, d.h.
     AB[c-f]*XY  findet z.B.  ABXY, ABcXY, ABdXY, ABceXY, ABcdcdfXY, etc
     AB[c-f]+XY  findet aber ABXY nicht, nur die anderen wie bei *
     Beispiele: ele[ck]tri  findet electri und elektri
               theat[er]+  findet Theater und theatre
               i[sz]abel+a findet Isabella, Izabella und Izabela

10. Steuerzeichen suchen
     AB\xCD   findet ABxCD
     Das Zeichen x soll vorkommen. Man setzt \ vor solche Zeichen,
     die sonst eine Steuerfunktion haben, also [ ] + * $ ^ _

11. \< : Wortanfang suchen
     \<abc   findet abc, aber nur wenn es an einem Wortanfang steht.
     Ein "Wort" beginnt mit Buchstabe oder Ziffer, d.h. es geht
     irgendein anderes Zeichen oder kein Zeichen voran, z.B. auch -

12. \> : Wortende suchen
     abc\>   findet abc, aber nur wenn es an einem Wortende steht.
     Hinter c soll also im Text ein Sonderzeichen oder nichts folgen.
     10 und 11 sind kombinierbar

13. \(...\) : Wiederholung eines Ausdrucks
     \(AB\)xyz\1   findet ABxyzAB
     \(AB\).*\1    findet AB...AB
                   mit beliebiger Zeichenfolge zwischen den beiden AB.
     Es koennen weitere Ausdruecke \(...\) auftreten, die danach mit \2,
     \3 etc. im selben Gesamtausdruck wiederholt werden koennen.



Neue FLEX-Befehlsoption:  fetch r
---------------------------------
Damit holt man aus einer geoeffneten allegro-Datendatei einen
kompletten Datensatz in die iV, wobei die Felder dann durch
LF # getrennt sind (das sind die Codes 10 und 35)
Das hat zur Folge, dass man mit nachfolgendem  insert  den
ganzen Datensatz an den Arbeitsspeicher uebergeben kann.
Wenn  fetch r  gegeben wird, muss zu dem Zeitpunkt aber der
Lesezeiger in der Datei auf dem ersten Zeichen des naechsten
Satzes stehen, normalerweise also auf der 0 von #00 (in den
Dateien sind die # nicht mitgespeichert).
Das stellt man sicher, indem man direkt vorher gibt
fetch b      // erstes Byte holen
fetch b4     // Satznummer holen
Der zweite Befehl entfaellt, wenn man eine Grunddatei (Typ .ALG)
vor sich hat. Nach dem  fetch r  steht der Lesezeiger genau auf
dem Steuerbyte des nächsten Satzes (Code 1, 8 oder 9).






Mehr Informationen über die Mailingliste Allegro