Erste Schritte mit regulären Ausdrücken (und ABAP)

Reguläre Ausdrücke waren bis vor einigen Tagen ein Buch mit sieben Siegeln für mich. Ich wusste zwar grundlegend wofür Sie genutzt werden, hatte aber noch nie mit ihnen gearbeitet, geschweige denn wirklich verstanden. Ich möchte dir an einem Beispiel meine Herangehensweise an das Thema zeigen. Falls es dir ähnlich geht wir mir, helfen dir die Informationen hoffentlich ebenfalls einen Einstieg in das Thema zu finden.

Doch zunächst was sind reguläre Ausdrücke überhaupt? Eine Suche auf Google führt uns zu folgender Beschreibung auf Wikipedia:

Ein regulärer Ausdruck (englisch regular expression, Abkürzung RegExp oder Regex) ist in der theoretischen Informatik eine Zeichenkette, die der Beschreibung von Mengen von Zeichenketten mit Hilfe bestimmter syntaktischer Regeln dient. Reguläre Ausdrücke finden vor allem in der Softwareentwicklung Verwendung. Neben Implementierungen in vielen Programmiersprachen verarbeiten auch viele Texteditoren reguläre Ausdrücke in der Funktion „Suchen und Ersetzen“. Ein einfacher Anwendungsfall von regulären Ausdrücken sind Wildcards.

WikipediaDie freie Enzyklopädie

Nicht wirklich verständlich? Dann hilft dir vielleicht das folgende Video weiter

Vereinfacht gesagt ist ein regulärer Ausdruck also ein Suchmuster für Zeichenketten. Du kannst einen solchen regulären Ausdruck also beispielsweise nutzen um einen bestimmten Teil eines Textes zu ermitteln.

Um die Anwendung zu verdeutlichen werden wir an folgendem Beispiel arbeiten:
Es besteht die Anforderung die HTTP-URLs aus einem HTML-Dokument zu lesen.

Dieses Dokument könnte sehr vereinfacht wie folgt aussehen, die gesuchten Bestandteile sind in den hervorgehobenen Zeilen grün markiert:

1
2
3
4
<html><body>
Welchen Sinn macht dieses Dokument? <a href="https://www.youtube.com/watch?v=DLzxrzFCyOs">Keinen?</a>
<p>Hey du wirst doch nicht wirklich <a href="https://www.youtube.com/watch?v=oHg5SJYRHA0">hier</a> klicken?
</body></html>

Ich wusste zwar, dass sich solche Anforderungen mit regulären Ausdrücken lösen lässt, aber nicht wie eben solche regulären Ausdrücke aussehen.

Bei meiner Suche bin ich auf eine Webseite gestoßen die mir den Umgang mit solchen Anforderungen und Regulären Ausdrücken extrem vereinfacht und zugänglich gemacht hat. Und ich denke sie hilft dir auch. Die Webseite nennt sich RegExr und sie ist ein Online-Tool zum bauen, testen und lernen von regulären Ausdrücken. Du findest die Webseite  hier.

Beginnen wir also mit dem Beispiel indem wir den oberen Text in RegExr einfügen:

Der verwendete reguläre Ausdruck
Der verwendete Beispieltext an dem der reguläre Ausdruck getestet werden soll
Einige Tools, z.B. eine Erklärung des regulären Ausdrucks
Die Navigationsleiste
Die Anzahl der gefundenen regulären Ausdrücke

Wie man an den farblich hervorgehobenen Bestandteilen erkennt, erfüllt der derzeit im Tool eingetragene reguläre Ausdruck ([A-Z]) nicht unsere Anforderungen. Er findet alle großgeschriebenen Buchstaben. Wir möchten URLs innerhalb des HTML <a> Tags finden.

Beginnen sollten wir mit der in der Navigationsleiste zu findenden Referenz und dem Cheatsheet in denen wir die Befehle und deren Bedeutung nachschlagen können – was in der Kombination mit dem Hervorheben der gefundenen Beispiele in Echtzeit auch Laien das bauen eines regulären Ausdrucks ermöglicht.

In meinem ersten Versuch baute ich nur mit Hilfe der Markierungen folgenden regulären Ausdruck:

[^"]*\.[a-z]{2,4}(\/[^"]*)?

Das Ergebnis sieht zunächst so aus, als sei dies bereits die Lösung unserer Anforderung.

Es wurden wie erwartet zwei Ergebnisse gefunden
Der genutzte reguläre Ausdruck
Die markierten Textstellen wurden gefunden

Wir sind in diesen Testdaten davon ausgegangen, dass der Anwender immer so vorgeht wie erwartet, und das jederzeit nur http bzw. https genutzt wird, und kein mailto oder ftp.

Prüfen wir also den regulären Ausdruck noch einmal mit den folgenden erweiterten Testdaten.

<html>
<body>
Welchen Sinn macht dieses Dokument? <a href="https://www.youtube.com/watch?v=DLzxrzFCyOs">Keinen?</a>
<p>Hey du wirst doch nicht wirklich <a w href="https://www.youtube.com/watch?v=oHg5SJYRHA0">hier</a> klicken?
Ich möchte dir nur im Text einen Link zeigen "http://www.youtube.com/watch?v=oHg5SJYRHA0", oder auch etwas anderes "test://www.youtube.com/watch?v=oHg5SJYRHA0"
oder auch einfach nur so eine URL http://www.youtube.com/watch?v=oHg5SJYRHA0
</body>
</html>
Es werden 5 Ergebnisse gefunden
Der ebenfalls vorher genutzte reguläre Ausdruck
Eine URL in Anführungszeichen, aber kein HTML-Link. Ist als Ergebnis nicht gewünscht.
Eine URL ohne Anführungszeichen, aber kein HTML-Link. Ist als Ergebnis nicht gewünscht und gibt eine zu große Ergebnismenge zurück.

Anhand der blau markierten Bereiche können wir sehen, dass das der reguläre Ausdruck für unsere Anforderung noch nicht ausreichend ist.

Die Anforderung besteht weiterhin daraus, dass nur die beiden grün markierten Bestandteile in den hervorgehobenen Zeilen gefunden werden.

Wir sollten uns also die genauere Bedeutung der Bestandteile unseres regulären Ausdrucks anschauen.

[^“]* = Beliebig viele Zeichen, die keine Anführungszeichen sind.
\. = Ein Punkt
[a-z]{2,4} = Zwei bis vier Zeichen, von a bis z. Also zwei bis vier kleine Buchstaben.
(\/[^“]*)? = Eine Gruppierung von Zeichen. Diese darf maximal einmal vorkommen. Die Gruppierung besteht aus einem /, gefolgt von beliebig vielen Zeichen, die keine Anführungszeichen sind.

Unser regulärer Ausdruck sucht also nach Zeichenketten die folgende Eigenschaften erfüllen:
Sie beginnt mit einer beliebigen Anzahl von Zeichen, die keine Anführungszeichen sind. Auf diese folgt ein Punkt. Dem Punkt folgen zwei bis vier kleine Buchstaben.
Daraufhin darf maximal einmal ein /, gefolgt von einem oder mehr Zeichen, außer einem Anführungszeichen, folgen.

Wie man an der Erklärung sieht, kann dieser reguläre Ausdruck wesentlich mehr Bestandteile finden, die in unserer Anforderung nicht gewünscht sind. So würden Beispielsweise auch in der Zeichenkette <a href=“ftp://xyz“>FTP?</a> der Ausdruck ftp://xyz gefunden werden.

Wir müssen unseren regulären Ausdruck also so anpassen, dass er die ungewünschten Ergebnisse nicht mehr findet.

Dabei müssen wir uns an die technischen Möglichkeiten der jeweiligen Systeme anpassen. Eine Möglichkeit zur Einschränkung der Ergebnisse wäre ein positive lookbehind, welches Beispielsweise mit (?<=href=“) ausdrücken würde, dass ein href=“ dem Suchergebnis vorangestellt sein muss, dieses aber nicht im Ergebnis inkludiert ist.

Da weder RegExr, noch ABAP positive lookbehind unterstützen müssen wir uns hier eine andere Möglichkeit überlegen.

Ein Lösungsansatz ist der folgende reguläre Ausdruck

(http|https)(\s*\S*)\.[A-Za-z]+(\/[^"\s]*)?(?=(\s*\S)*<\/a>)(?=")

Dieser reguläre Ausdruck sucht nach einer Zeichenfolge, die mit http oder https beginnt. Darauf folgen beliebig viele Zeichen, auf die ein Punkt folgt. Nach diesem Punkt folgen ein oder mehr Buchstaben. Auf die Buchstaben darf maximal einmal eine Gruppe aus einem /, sowie beliebig vielen Zeichen außer Anführungszeichen und Leerzeichen bzw. Zeilenumbrüchen folgen. Nach dem Ergebnis muss sowohl ein beliebiger Inhalt folgen, der mit </a> endet, als auch ein Anführungszeichen. Diese sind jedoch nicht Teil des Ergebnisses.

Der Unterschied der regulären Ausdrücke wird sehr deutlich, wenn man beide mit etwas umfangreicheren Daten testet.

Der vorherige reguläre Ausdruck ist vollständig sichtbar, wenn der Schieberegler nach ganz links geschoben ist. Der neue Ausdruck ist vollständig sichtbar, wenn der Schieberegler nach ganz rechts geschoben ist.

Nun müssen wir noch prüfen ob sich dieser reguläre Ausdruck auch in ABAP nutzen lässt und sich dort auch wie erwartet verhält.

Eine Möglichkeit für solche Tests ist das Programm DEMO_REGEX_TOY. Dieses lässt sich wie gewohnt über die Transaktionen SE38 oder SE80 aufrufen.

Der genutzte reguläre Ausdruck
Einstellungsmöglichkeiten
Der Text an dem der reguläre Ausdruck getestet werden soll
Das Ergebnis

Wie man an den Ergebnissen erkennt, funktioniert der reguläre Ausdruck in diesem Testwerkzeug nicht reibungslos.

Es ist nun zu prüfen, wie sich der reguläre Ausdruck im geplanten Einsatzumgebung verhält. Ein Test an den erwarteten Daten mit der genutzten Methode ist zu empfehlen.

Dies führt jedoch für diese kurze Einführung zu weit und wir werden an dieser Stelle mit dem Beispiel pausieren.

Zusammenfassend empfehle ich also folgende herangehensweise:

Suchen

Zunächst würde ich oberflächlich nach der Anforderung und dem Themengebiet suchen. Unter Umständen findet man bereits einen Ansatz oder eine Lösung. Selbst falls dies nicht der Fall ist erhält man bereits einen groben Überblick über das Thema. In diesem Fall habe ich zunächst ganz allgemein nach regulären Ausdrücken gesucht. Dabei bin ich auf die erwähnte Seite RegExr gestoßen, welche im Folgenden mein Ausgangspunkt wurde. Dort konnte ich mir auch anhand der Community Beiträge einen Überblick über den Aufbau von anderen regulären Ausdrücken machen.

Prototyp

Daraufhin würde ich aus dem bisher gesammelten Wissen einen Prototypen erstellen. Dies war in diesem Fall der erste reguläre Ausdruck, der noch recht rudimentär und schnell erstellt war.

Testen

Der jeweilige Stand des Prototypen ist dann zu testen.und es ist zu prüfen ob dieser bereits die Anforderung oder Teile der Anforderung abdeckt. Wie im Beitrag erwähnt konnte der erste Prototyp schon einige Anforderungen erfüllen, war aber an anderen Stellen noch unscharf. Er konnte also noch nicht als endgültige Lösung verwendet werden.

Anpassen

Aus den Informationen der vorherigen Schritte oder anderer Quellen ist der Prototyp anzupassen. Aus den aufgetretenen Fehlern wurden die Notwendigkeiten zur Anpassung deutlich. Also habe ich den ersten Ausdruck solange angepasst, bis ich zur bisherigen Lösung kam.

Finalisieren

Diese Schritte sind zu wiederholen, bis man mit dem Ergebnis zufrieden ist und die unter Umständen vorher beinhalteten Ungenauigkeiten angepasst wurden.

Dies war für mich der letzte angegebene reguläre Ausdruck. Dieser war zwar noch nicht perfekt, aber für den bisherigen Zweck geeignet. Sollten jedoch bisher nicht beachtete Ungenauigkeiten auftreten, so ist eine erneute Anpassung notwendig.

Kennst du ein besseres Beispiel, hast du einen anderen Ansatz oder eine bessere Lösung?
Besteht an einer Stelle meines Beitrages Anpassungsbedarf?

Dann schreib gerne einen Kommentar!

Beste Grüße,

Tobias

Hinterlasse eine Antwort