1. Allgemeines und ein Beispiel
Laut [1] gibt es, nach einer längeren Pause seit 2019, wieder eine Betreuung und Weiterentwicklung der Pascal RegEx-Unit. Es gibt für FreePascal noch weitere Engines, die aber aktuell nicht mehr unterstützt werden. Diese Wiki-Seite liefert auch das Beispiel, von dem ich ausgegangen bin, hier die wesentliche Information der verlinkten Seite:
Code: Alles auswählen
Mit der RegExpr von Sorokin ist es sehr einfach zu überprüfen, ob ein Ausdruck (expression) in einer Zeichenkette (string) vorkommt.
Dazu erstellen Sie eine Instanz von TRegExpr. Dann übergeben Sie Ihren regulären Ausdruck der Eigenschaft
TRegExpr.Expression. Um den Regulären Ausdruck zu überprüfen führen Sie das Ganze mit der Methode
Exec aus. Wenn der Reguläre Ausdruck in der Zeichenkette (String) vorkommt, dann gibt die Methode Exec
den Wert True (Wahr) zurück.
var
RegexObj: TRegExpr;
begin
RegexObj := TRegExpr.Create;
RegexObj.Expression := '.*login.*';
if RegexObj.Exec('Bitte finde das Wort login in diesem Satz.') then WriteLn('Das Wort login wurde im Satz gefunden!');
RegexObj.Free;
end;
Sehr empfehlenswert finde ich die Doc [3] vom Betreuer selbst, sie ist auch in Deutsch [4] erhältlich, aber leider nur unvollständig übersetzt.
[1] https://wiki.freepascal.org/RegEx_packages
[2] https://wiki.lazarus.freepascal.org/IDE ... xpressions
[3] https://regex.sorokin.engineer/en/lates ... sions.html
[4] https://regex.sorokin.engineer/de/lates ... sions.html
2. Praktisches
Wer FreePascal noch nicht auf dem Computer hat - apt install fpc
schaufelt das Benötigte auf die Kiste.
Sinnvollerweise legt man ein Verzeichnis $HOME/pas/ für alles Weitere an.
compiliert und gleichzeitig gelinkt wird mit fpc progname.pas
was eine Objektdatei progname.o sowie ein ausführbares Progr. mit dem Namen progname mit passenden Rechten erzeugt. Vermutlich ist nach ~/pas/ kein Exec-Pfad gelegt, deshalb Programmstart mit ~/pas/progname
Für die Bearbeitung der Sources taugt ein beliebiger Editor, selbst Mousepad macht ein akzeptables Syntax-Highlightning. Wer an die alte Turbo-5ff-Oberfläche erinnert werden möchte, kann auch einfach fp starten; muss aber erst den Bug beseitigen, der hier [5] behandelt wurde, sonst werden keine Units gefunden.
Dann funktioniert zumindest das Compilieren, ich hatte dann aber noch weitere Schwierigkeiten bekommen, denen ich nicht nachgegangen bin.... im IDE-Menü "Options/Directories/Units"
"/usr/lib/x86_64-linux-gnu/fpc/3.2.0/units/x86_64-linux/*/" gesetzt
[5] viewtopic.php?p=1303421#p1303363
Schließlich gibt es natürlich noch die alles-erschlagende Oberfläche Lazarus, die extra installiert werden muss.
Ich nutze seit einem Tipp hier vom Debian-Forum Geany; flott, klein, übersichtlich, und es bringt für die fpc-Compilierung auch gleich die passenden Einstellungen mit.
Ansonsten unter Erstellen -> Kommandos zum Erstellen konfigurieren -> kompilieren >fpc "%f"< eintragen
Zum 1. Programm
41754
Wir sehen, dass (das Objekt) re am Anfung "created" und gleichzeitig eine RegExpr. zugewiesen wird. Der Aufruf re.Exec mit dem zu durchsuchenden String liefert TRUE, wenn mindestens ein Treffer vorhanden ist. Dieser Match wird per WriteLn (mit Zeilenvorschub) geschrieben und in der While-Loop nach weiteren Matches gesucht. Am Schluss wird das Objekt wieder freigegeben. Also klassisches, prozedurales Pascal, auch wenn re einen Objekt-Typ darstellt.
Arbeitsvorschläge:
den RE so ändern, dass
1) alle "l" ausgeben werdem
2) nur das 2. "hello" finden und zusammen mit den nachfolgenden 2 Zeichen ausgeben (damit man sieht, dass es tatsächlich das 2. "hello" ist).
3) Was ist der Unterschied in der Behandlung der Zeichen IN der inneren Klammer "()" und außerhalb dieser Klammer?
2. Programm
-jetzt ohne vorgegebene Lösung: 41763
Hier wurde das Beispiel in eine Prozedur verpackt. Die Matches werden weiterhin einzeln ausgegeben, allerdings jetzt ohne Zeilenvorschub, und zwecks besserer Übersicht außerdem durch einen Unterstrich getrennt. Erst am Ende gibt es einen Zeilenvorschub.
Es folgen im Hauptprogramm einige Aufrufe dieser Prozedur. Leider matcht die RE im Beispiel immer den ganzen zu durchsuchenden Text, Eure Aufgabe bestehen also darin, statt des All-Matchers ".*" die jeweils passende RE einzutragen.
Wenn jemand mit diesem Programm weitere Aufgaben erarbeitet / ertestet - immer her damit!
Nun folgt ein Programm zum Durchsuchen von Textdateien
neue Version: 41769
alte Version: 41757
Die Prozedur FindMatches schreibt jetzt nicht mehr direkt auf den Bildschirm, sondern "addiert" (concateniert) die Matches auf einen Ausgabe-String.
Für die Ausgabe gibt es zwecks Übersichtlichkeit eine eigene kleine Procedure. Das Hauptprogramm macht erst mal einen Plaustest, liest dann die Textdatei sequentiell und lässt die Zeilen in "Find_and_write" weiterbearbeiten, welches sie dann an FindMatches weitergibt. Ich vermute, dass meine Kommentare zum Verständnis ausreichen, ansonsten einfach nachfragen.
Wegen der zu übergebenden Kommandozeilen-Parameter ist es empfehlenswert, das Prog in einem Terminal ablaufen zu lassen, ansonsten müssten die Params in die IDE hineingefummelt werden. Zum Ausprobieren verwende ich wieder die famose schwaebische Kunde; also z.B. alle "sch" einschließlich zweier Folgezeichen geht so:
___________________
Code: Alles auswählen
~/pas/test_regex "(sch..)" schwaebische-kunde.txt
1 sche
2<Leerzeile>
9 sche
11 schwa
15 schwa
22 sche
23 schie
30 schwa
31 schen
37 schwi
46 schni
47 schaa
Das Verhalten ist somit dem egrep -no "(sch..)" schwaebische-kunde.txt sehr ähnlich, außer der Anzeige der Leerzeile, die ja bei Bedarf auch aus dem Progr. leicht heraus genommen werden kann. Ich fand es interessant, den Output jeweils mit egrep zu vergleichen. Und ach ja, die RE muss gequotet werden, sonst meckert die bash.
Weitere Arbeitsvorschläge:
- Finde alle Auslassungszeichen "'"
- alle Auslassungszeichen die einem b folgen, das b selber aber nicht.
- jetzt mal etwas pfiffiger: Zeige alle Sätze, die den Buchstaben D enthalten (groß oder klein egal) bis genau zum ersten Vorkommen und einschließlich dieses Zeichens.
- zeige alle Wörter einzeln unter Verwendung der Zeichenklasse \w, was dem [:alpha:] im egrep entspricht.
- zeige alle Sonderzeichen und vergleiche "^\w" mit "\W"
Falls ihr Lust dazu verspürt - denkt Euch weitere Aufgaben aus, und stellt sie vor.
Zum Schluss noch ein kleines Anwendungsbeispiel, welches eine Datei, die Dateinamen von Bildern enthält, mittels Regex durchsucht. Diese kann z.B. mit find erzeugt werden. Die Treffer werden mit einem Bilder-Viewer angezeigt, der ristretto hat sich als recht geeignet erwiesen.
41758
Ich denke, ich werde das Beispiel in eine für meine Bildersammlung angepasste Anwendung ausbauen, dies ist nur ein „proof of concept“ – so heißt das wohl heute, glaub ich. Für eine brauchbare Anwendung würde man z.B. die Eingabe des RE entsprechend aufbereiten, vielleicht verschiedene Bildbetrachter zur Auswahl stellen, auf jeden Fall verschiedene Bilder-Listen vorhalten und eventuell eine kleine Dateiverwaltung zum Umbenennen und Löschen von Bilderdateien anflanschen.
Vermutlich gibt es auch Units, die Bilder direkt anzeigen können, aber den Aufruf der bash mit beliebigen Inhalten direkt aus dem Programm heraus finde ich unschlagbar bequem und es mag Euch vielleicht zu weiteren Experimenten anregen, beispielsweise mit Musikdateien.
Viel Spaß!
TuxPeter