Reguläre Ausdrücke sind ein wichtiges Konzept in der Programmierung, und damit auch in der ABAP-Programmierung im SAP-System. Mithilfe von regulären Ausdrücken kannst Du einfach in Zeichenketten nach einem gewissen Muster suchen. Dadurch kannst Du Zeichenketten validieren und verändern. Mithilfe von wenigen Zeilen Code kannst Du effizient und einfach eine Suche durchführen. Eine Suche mit regulären Ausdrücken in ABAP ist leistungsfähiger als herkömmliche SAP-Muster.
In diesem Artikel erkläre ich Dir, was man unter regulären Ausdrücken im Allgemeinen versteht, wie Du sie vorab überprüfen kannst und wie Du in der Programmiersprache ABAP reguläre Ausdrücke verwenden kannst. Gerade für Einsteiger sind reguläre Ausdrücke komplex. Wenn Du sie aber verstehst, wirst Du den großen Funktionsumfang und Nutzen von regulären Ausdrücken schätzen.
Reguläre Ausdrücke – Definition
Reguläre Ausdrücke (auch RegEx genannt) sind Muster, die zum Abgleichen von Zeichenkombinationen in Zeichenketten verwendet werden. Ein regulärer Ausdruck besteht aus Buchstaben und Symbolen, die ein Suchmuster bilden.
Viele Programmiersprachen erlauben es Entwicklern, reguläre Ausdrücke zu definieren und sie dann zu verwenden. Typische Anwendungsfälle sind folgende:
- Text nach bestimmten Muster überprüfen
- Teile eines Textes finden
- Teile eines Textes extrahieren
- Text durch anderen Text ersetzen
In regulären Ausdrücken können Metazeichen verwendet werden. Dabei handelt es sich um Symbole, die für die Suche keine wörtliche Bedeutung haben, aber zur Definition des Suchmusters verwendet werden. Das Sternchen (*) z.B. kann für beliebige Zeichen stehen.
Literale
Reguläre Ausdrücke bestehen im Allgemeinen aus Symbolen und Zeichen (Literalen). In der nachstehenden Tabelle werden einige der häufig verwendeten Literale aufgelistet.
Literal | Beschreibung |
---|---|
\ | Escape-Zeichen für Sonderzeichen |
. | Platzhalter für ein beliebiges einzelnes Zeichen |
\d | Platzhalter für eine beliebige Einzelziffer |
[] | Definition einer Wertemenge für einzelne Zeichen |
[ – ] | Definition eines Bereichs in einer Wertemenge für einzelne Zeichen |
? | Ein oder kein einzelnes Zeichen |
* | Verkettung von beliebig vielen Einzelzeichen |
+ | Verkettung von beliebig vielen Einzelzeichen (mindestens ein Zeichen) |
| | Verkettung von zwei alternativen Ausdrücken |
^ | Ankerzeichen für den Anfang einer Zeile |
$ | Ankerzeichen für das Ende einer Zeile |
\< | Anfang eines Wortes |
> | Ende eines Wortes |
\b | Anfang oder Ende eines Wortes |
\w | Jeder Buchstabe, jede Ziffer und jeder Unterstrich |
\s | Leerzeichen oder Tabulator |
Beispiel
Wir haben als Beispiel diesen Text: ERP UP – Wissenswertes in SAP ERP und SAP S/4HANA. Nun möchten wir in diesem Text prüfen, ob der Begriff „ERP UP“ darin vorkommt. Es kann hierfür verschiedene Schreibweisen geben: ERP UP, ERP-UP, erp up, erp-up. Und genau hierfür erstellen und nutzen wir einen regulären Ausdruck, um diese Schreibweisen zu überprüfen. Der reguläre Ausdruck hierfür kann folgendermaßen aussehen:
[eE][rR][pP][ |-][uU][pP]
Hier gibt es weitere einfache Beispiele für reguläre Ausdrücke:
Regulärer Ausdruck | Beschreibung | Beispiel |
---|---|---|
a? | „a“-Zeichen oder nichts. | a |
a* | Kein oder mehrere aufeinanderfolgende „a“-Zeichen. | aa |
a+ | Ein oder mehrere aufeinanderfolgende „a“-Zeichen. | aa |
a{3} | Drei aufeinanderfolgende „a“-Zeichen | aaa |
a{3,} | Drei oder mehrere aufeinanderfolgende „a“-Zeichen | aaaa |
a{3,6} | Drei bis sechs aufeinanderfolgende „a“-Zeichen | aaaaaa |
\w{5} | Beliebiges Wort mit fünf Buchstaben oder einer fünfstelligen Zahl | ERPUP |
\d{10} | 10-stellige Zahl | 0123456789 |
[a-z]{5,} | Fünf- oder mehrstelliges Wort in Kleinbuchstaben | erpup |
[a-zA-Z] | Ein Buchstabe in Groß- oder Kleinschreibung | Z |
Tool für reguläre Ausdrücke
Es gibt das kostenlose Tool regex101, mit dem Du kostenlos reguläre Ausdrücke erstellen und prüfen kannst. Gib doch einfach einen regulären Ausdruck und einen Text ein und überprüfe eigenständig das Ergebnis. Das geniale hierbei ist vor allem, dass man rechts auf Englisch die Erklärung hierfür angezeigt bekommt.
Reguläre Ausdrücke in ABAP
In der Programmiersprache ABAP kannst Du ebenfalls reguläre Ausdrücke verwenden. ABAP unterstützt reguläre Ausdrücke in den Anweisungen FIND und REPLACE und über die ABAP-Klassen CL_ABAP_REGEX und CL_ABAP_MATCHER. Die Klasse CL_ABAP_MATCHER wendet einen mit CL_ABAP_REGEX erzeugten regulären Ausdruck entweder auf eine Zeichenkette oder eine interne Tabelle an.
Verwendest Du einen syntaktisch falschen regulären Ausdruck, wird die Ausnahme CX_SY_INVALID_REGEX ausgelöst.
Ein regulärer Ausdruck kann syntaktisch korrekt sein, aber zu komplex für die Ausführung der ABAP-Anweisung FIND oder REPLACE. Wenn dem so ist, wird eine behandelbare Ausnahme der Klasse CX_SY_REGEX_TOO_COMPLEX ausgelöst.
Regulärer Ausdruck in ABAP – FIND
Du kannst mit dem ABAP-Begriff FIND reguläre Ausdrücke verwenden und damit nach einem bestimmten Suchmuster in einer Zeichenkette suchen. Die Syntax hierfür lautet folgendermaßen:
FIND REGEX <RegEx> IN <Text> RESULTS <Ergebnisse>.
Anstatt RESULTS kannst Du auch MATCH COUNT, MATCH OFFSET oder MATCH LENGTH angeben, um die Anzahl der Treffer, das Offset oder die Länge des Ergebnisses zu ermitteln.
Beim FIND-Befehl schreibt man die Ergebnisse der Suche in eine interne Tabelle des Typs MATCH_RESULT_TAB. Dabei handelt es sich um einen Tabellentyp, der als Zeilentyp die Struktur MATCH_RESULT enthält. Hierbei gibt es die wichtigen Attribute OFFSET und LENGTH. OFFSET enthält den Index im String, an dem der Teilstring gefunden wurde. Der Index beginnt mit 0. Sollte der Teilstring also an der ersten Stelle gefunden werden, enthält OFFSET den Wert 0. Das Attribut LENGTH gibt die Länge des Teilstrings an. Den gewünschten Teilstring kannst Du einfach durch folgenden Begriff ermitteln.
" Syntax String+OFFSET(LENGTH) " Beispiel der Variable lv_input " An der vierten Stelle wird ein Teilstring der Länge 2 ermittelt " lv_input = 'ERP UP' lv_input+3(2) "UP
Bei der Suche wird die sogenannte „leftmost-longest“-Regel angewendet. Dabei wird der Teil der Zeichenkette als Erstes ermittelt, der am weitestens links steht. Gibt es mehrere Übereinstimmungen, wird der längste Teil ermittelt.
Als Beispiel möchten wir Straßennamen validieren. Wir gehen zur Vereinfachung davon aus, dass ein Straßenname immer mit „Str.“ endet. Dabei soll die Groß- und Kleinschreibung von „Str.“ ignoriert werden. Hierbei wähle ich folgenden Straßennamen: „Haupstr.“. Hierfür kann man als Beispiel folgenden regulären Ausdruck verwenden:
.*[sS]tr\.
In einem ABAP-Programm kann es bspw. folgendermaßen aussehen:
DATA: lv_regex TYPE c LENGTH 10 VALUE '.*[sS]tr\.', lv_input_regex TYPE text100, lt_regex_result TYPE match_result_tab, ls_regex_result TYPE match_result. lv_input_regex = 'Haupstr.'. FIND REGEX lv_regex IN lv_input_regex RESULTS lt_regex_result. IF sy-subrc = 0. READ TABLE lt_regex_result INDEX 1 INTO ls_regex_result. WRITE: / lv_input_regex+ls_regex_result-offset(ls_regex_result-length). ELSE. WRITE: / 'Nichts gefunden'. ENDIF.
Findet der REGEX-Befehl kein Teilstring, wird der Rückgabewert 4 in der Systemvariable sy-subrc zurückgegeben.
Außerdem kannst Du die Anweisung „FIND ALL OCCURRENCES OF REGEX“ verwenden, um die Anzahl der Teilstrings in einer Zeichenkette zu ermitteln. Die Syntax hierfür lautet:
FIND ALL OCCURRENCES OF REGEX <RegEx> in <Text> RESULTS <Ergebnisse>.
In einem ABAP-Programm kann es bspw. folgendermaßen angewendet werden:
DATA: lv_regex TYPE c LENGTH 12 VALUE '[eE][rR][pP]', lv_input_regex TYPE text100, lv_count TYPE i. lv_input_regex = 'ERP UP, ERP-UP, erp up, erp-up'. FIND ALL OCCURRENCES OF REGEX lv_regex IN lv_input_regex MATCH COUNT lv_count. IF sy-subrc = 0 AND lv_count > 0. WRITE: / 'Der Begriff "ERP" kommt ', lv_count, ' mal vor.'. ELSE. WRITE: / 'Nichts gefunden'. ENDIF.
Regulärer Ausdruck in ABAP – REPLACE
Du kannst mit dem ABAP-Begriff REPLACE reguläre Ausdrücke verwenden und damit in einem Text einen bestimmten Teil entfernen. Die Syntax hierfür lautet folgendermaßen:
REPLACE REGEX <RegEx> IN <Text> WITH <Ersatz>.
Dabei wird der erste gefundene Teilstring ersetzt und nicht alle. Ich möchte das anhand von einem Beispiel näher erläutern. Wir haben erneut unseren Text „ERP UP, ERP-UP, erp up, erp-up“ und den regulären Ausdruck „[eE][rR][pP]“, um nach dem Wort „ERP“ zu suchen. Im Text kommt dieser vier mal vor. Wenn ich nun die folgende Anweisung verwende, wird nur der erste Treffer ausgetauscht:
"Davor: ERP UP, ERP-UP, erp up, erp-up REPLACE REGEX lv_regex IN lv_input_regex WITH ''. "Danach: UP, ERP-UP, erp up, erp-up
In einem Beispielprogramm wird es folgendermaßen integriert:
DATA: lv_regex TYPE c LENGTH 12 VALUE '[eE][rR][pP]', lv_input_regex TYPE text100. lv_input_regex = 'ERP UP, ERP-UP, erp up, erp-up'. REPLACE REGEX lv_regex IN lv_input_regex WITH ''. IF sy-subrc = 0. WRITE: / lv_input_regex. ELSE. WRITE: / 'Nichts gefunden'. ENDIF.
Wenn Du nun alle möglichen Treffer austauschen möchtest, verwendest Du die Anweisung „REPLACE all OCCURRENCES OF REGEX“. Die Syntax hierfür lautet folgendermaßen:
REPLACE ALL OCCURRENCES OF REGEX <RegEx> IN <Text> WITH <Ersatz>.
Wenn wir diese Anweisung im oberen Programm verwenden, ist die Ausgabe “ UP, -UP, up, -up“, da alle Begriffe „ERP“ ersetzt werden.
Wenn man ein ungültiges Muster nach dem Zusatz „WITH“ angibt, wird die Ausnahme CX_SY_INVALID_REGEX_FORMAT ausgelöst.
Regulärer Ausdruck in ABAP – CL_ABAP_REGEX
Anstatt direkt den regulären Ausdruck in FIND und REPLACE anzugeben, kannst Du die ABAP-Klasse CL_ABAP_REGEX verwenden. Hierfür gibst Du bei der Erstellung einer Instanz im Konstruktor den regulären Ausdruck an und gibst diese im ABAP-Befehl „FIND“ an.
Wenn wir bei der Suche eines Wortes, das „Str.“ enthält bleiben, kann ein Beispielprogramm folgendermaßen aussehen:
DATA: lv_regex TYPE c LENGTH 10 VALUE '.*[sS]tr\.', lc_regex TYPE REF TO cl_abap_regex, lv_input_regex TYPE text100, lt_regex_result TYPE match_result_tab, ls_regex_result TYPE match_result. lv_input_regex = 'Haupstr.'. TRY. CREATE OBJECT lc_regex EXPORTING pattern = lv_regex . CATCH cx_sy_regex . ENDTRY. FIND REGEX lc_regex IN lv_input_regex RESULTS lt_regex_result. IF sy-subrc = 0. READ TABLE lt_regex_result INDEX 1 INTO ls_regex_result. WRITE: / lv_input_regex+ls_regex_result-offset(ls_regex_result-length). ELSE. WRITE: / 'Nichts gefunden'. ENDIF.
Du kannst die Instanz der ABAP-Klasse insgesamt in folgenden Anweisungen anwenden:
- FIND REGEX
- FIND ALL OCCURRENCES OF REGEX
- REPLACE REGEX
- REPLACE ALL OCCURRENCES OF REGEX
In den vorherigen Beispielen kannst Du somit die Variable lv_regex mit lc_regex ersetzen und erhältst das gleiche Ergebnis.
Regulärer Ausdruck in ABAP – CL_ABAP_MATCHER
Die ABAP-Klasse CL_ABAP_MATCHER ist ebenfalls sehr mächtig und kann im Rahmen von regulären Ausdrücken verwendet werden. Bei der Erstellung einer Instanz dieser Klasse wird der reguläre Ausdruck in der ABAP-Klasse CL_ABAP_REGEX gehalten.
Mit der statischen Methode kannst Du z.B. überprüfen, ob anhand eines regulären Ausdrucks ein Muster in einem Text zutrifft. Das ABAP-Programm kann bspw. folgendermaßen aussehen:
DATA: lv_regex TYPE c LENGTH 12 VALUE '[eE][rR][pP]', lv_input_regex TYPE text100, lc_matcher TYPE REF TO cl_abap_matcher, lv_success TYPE flag. lv_input_regex = 'ERP UP, ERP-UP, erp up, erp-up'. CALL METHOD cl_abap_matcher=>contains EXPORTING pattern = lv_regex text = lv_input_regex RECEIVING success = lv_success. IF lv_success IS NOT INITIAL. WRITE: / 'Muster im Text gefunden'. ELSE. WRITE: / 'Nichts gefunden.'. ENDIF.
Alternativ kannst Du die statische Methode CREATE erwenden, um eine Instanz zu erzeugen und mit der Methode FIND_NEXT prüfen, ob das Suchmuster enthalten ist.
DATA: lv_regex TYPE c LENGTH 12 VALUE '[eE][rR][pP]', lv_input_regex TYPE text100, lc_matcher TYPE REF TO cl_abap_matcher. lv_input_regex = 'ERP UP, ERP-UP, erp up, erp-up'. lc_matcher = cl_abap_matcher=>create( pattern = lv_regex text = lv_input_regex ). IF lc_matcher->find_next( ) = 'X'. WRITE: / 'Suchmuster im Text vorhanden.'. ELSE. WRITE: / 'Nichts gefunden.'. ENDIF.
Möchtest Du mit der Klasse CL_ABAP_MATCHER einen Teil des Textes ersetzen, kannst Du die Methode REPLACE_NEXT oder REPLACE_ALL nutzen.
DATA: lv_regex TYPE c LENGTH 12 VALUE '[eE][rR][pP]', lv_input_regex TYPE text100, lc_matcher TYPE REF TO cl_abap_matcher. lv_input_regex = 'ERP UP, ERP-UP, erp up, erp-up'. lc_matcher = cl_abap_matcher=>create( pattern = lv_regex text = lv_input_regex ). " Ersten Treffer ersetzen lc_matcher->replace_next( '' ). " Alle Treffer ersetzen lc_matcher->replace_all( '' ). WRITE: / lc_matcher->text.
Über den Autor
Mein Name ist Andreas Geiger und ich bin ein erfahrener Senior SAP Berater. Mit mehr als 10 Jahren Berufserfahrung habe ich mehrere SAP-Projekte erfolgreich abgeschlossen und umfangreiche Kenntnisse in verschiedenen Bereichen wie SAP FI, SAP MM und ABAP erworben. Nun möchte ich mein Wissen mit Dir teilen, um Dir einen Mehrwert zu bieten und Dich bei Deiner täglichen Arbeit mit dem SAP-System zu unterstützen.
ERP UP unterstützen
Wenn Du mit ERP UP zufrieden bist, kannst Du mich gerne unterstützen. Dabei gibt es unzählige Möglichkeiten, wie Du mich einfach und schnell unterstützen kannst. Wie Du genau ERP UP unterstützen kannst, erfährst Du hier. Vielen Dank.