
ABAP - XCO Reguläre Ausdrücke
Schauen wir uns einmal die XCO Klassen für die regulären Ausdrücke an und wie damit recht einfach REGEX gegen Texte und Eingaben in ABAP Cloud absetzen kannst. Dabei vergleichen wir auch mit klassischem ABAP.
Inhaltsverzeichnis
Die XCO Klassen sind Hilfsklassen die verschiedene Funktionen des Alltags gebündelt unter einer öffentlichen API zur Verfügung stellen. Weitere Informationen und eine Übersicht über die XCO Bibliotheken findest du auf der Übersichtsseite.
Einleitung
Immer wieder kommen wir in der Entwicklung an Stellen, da wollen wir den User-Input prüfen und validieren oder lassen nur bestimmte Eingaben zu. Um diese Validierung machen zu können, kommen Reguläre Ausdrücke oder kurz REGEX zum Einsatz. Dabei werden Texte gegen bestimmte Muster abgeglichen. Als Standard gilt hier zum Beispiel der Vergleich einer E-Mail Adresse, wo ein @ Zeichen erwartet wird und ein Punkt für eine Domain. Darüber hinaus können noch weitere Prüfungen durchgeführt werden.
Engine
Für Reguläre Ausdrücke gibt es verschiedene Engines für die Validierung. Über die Factory ENGINE der Klasse XCO_CP_REGULAR_EXPRESSION kannst du dir verschiedene Methoden erzeugen lassen. Hier auch den Konstruktor beachten, da du darüber noch zusätzliche Einstellungen vornehmen kannst.
Hinweis: Die Empfehlung liegt meist bei der Nutzung von PCRE, früher wurde vor allem POSIX als Standard verwendet. Das DEFAULT Attribut bei den meisten Parametern und der Factory ist allerdings immer noch POSIX.
Extraktion
Im ersten Beispiel schauen wir uns eine String Extraktion an und wie wir Bestandteile aus einem String in eine Tabelle extrahieren können. Als Beispiel nehmen wir einen String, aus dem wir alle Wörter extrahieren wollen, die "is" als Bestandteil haben. Hierbei verwenden wir PCRE als Engine.
CONSTANTS search_string TYPE string VALUE `This is my new string class.`.
Classic
Über das Statement FIND und den Zusatz PCRE erhalten wir eine Ergebnistabelle mit allen Fundorten zurück. Im Anschluss müssen wir nur noch über die Tabelle gehen und können aus dem String die Stellen in unsere Ergebnistabelle extrahieren.
FIND ALL OCCURRENCES OF PCRE `\w*is\w*` IN search_string RESULTS DATA(found_parts).
LOOP AT found_parts INTO DATA(found_part).
INSERT search_string+found_part-offset(found_part-length) INTO TABLE search_results.
ENDLOOP.
Modern
Beim modernen Ansatz verwenden wir die neuen Funktionen FIND und FIND_END und nicht mehr die klassischen Statements. Allerdings erzeugen wir damit auch viel mehr Code und erhalten nicht mehr eine Tabelle mit dem Ergebnis, sondern müssen in einer Schleife von Stelle zu Stelle springen und die Extraktion durchführen.
DATA(ld_start) = 0.
DO.
DATA(ld_position) = find( val = search_string
pcre = `\w*is\w*`
off = ld_start ).
IF ld_position = -1.
EXIT.
ENDIF.
DATA(ld_to) = find_end( val = search_string
pcre = `\w*is\w*`
off = ld_start ).
INSERT substring( val = search_string
off = ld_position
len = ld_to - ld_position ) INTO TABLE search_results.
ld_start = ld_to.
ENDDO.
XCO
Bei der XCO Bibliothek können wir über das String Objekt gehen. Die Methode GREP bietet die Möglichkeit über einen REGEX eine Extraktion durchzuführen und ein STRINGS Objekt zu erhalten. Allerdings müssen wir dann auch etwas den Ausdruck anpassen und können diesen nicht 1:1 aus den bisherigen Beispielen übernehmen.
search_results = xco_cp=>string( search_string )->grep(
iv_regular_expression = `\w*is\w*`
io_engine = xco_cp_regular_expression=>engine->pcre( )
)->value.
Ergebnis
Als Ergebnis erhalten wir eine Ausgabe in die Konsole, hier sollten immer die gleichen zwei Bestandteile auftauchen. Aktuell gibt es aber bei der XCO Bibliothek eine Abweichung im Ergebnis, der wir aktuell noch auf der Spur sind. Grundsätzlich funktioniert die Funktion, siehe Unit Test in der Klasse. Allerdings scheint der "Word Match" nicht zu greifen.
Prüfung
In diesem Beispiel machen wir eine Überprüfung einer Eingabe und verwenden dazu die Klasse XCO_CP=>REGULAR_EXPRESSION um uns für eine REGEX und eine Engine ein Objekt zu erzeugen. Über die Methode MATCHES können wir dann vergleichen, ob der String mit der Abfrage übereinstimmt. In diesem Fall wollen wir wissen, ob nur Großbuchstaben, Zahlen und Unterstriche im String enthalten sind.
DATA(regex) = xco_cp=>regular_expression( iv_value = `^[A-Z0-9_]+$`
io_engine = xco_cp_regular_expression=>engine->pcre( ) ).
IF regex->matches( `MY_CONTENT` ).
ENDIF.
Vollständiges Beispiel
Hier findest du noch einmal die komplette Klasse mit dem gesamten Beispiel. Zusätzlich findest du noch im GitHub Repository alle anderen XCO Beispiele aus der Serie.
CLASS zcl_bs_demo_xco_pcre_test DEFINITION
PUBLIC FINAL
CREATE PUBLIC.
PUBLIC SECTION.
INTERFACES if_oo_adt_classrun.
CONSTANTS search_string TYPE string VALUE `This is my new string class.`.
PRIVATE SECTION.
METHODS extract_string
IMPORTING !out TYPE REF TO if_oo_adt_classrun_out.
METHODS validate_string
IMPORTING !out TYPE REF TO if_oo_adt_classrun_out.
ENDCLASS.
CLASS zcl_bs_demo_xco_pcre_test IMPLEMENTATION.
METHOD if_oo_adt_classrun~main.
extract_string( out ).
validate_string( out ).
ENDMETHOD.
METHOD extract_string.
DATA search_results TYPE string_table.
" Classic
FIND ALL OCCURRENCES OF PCRE `\w*is\w*` IN search_string RESULTS DATA(found_parts).
LOOP AT found_parts INTO DATA(found_part).
INSERT search_string+found_part-offset(found_part-length) INTO TABLE search_results.
ENDLOOP.
out->write( `Classic:` ).
out->write( search_results ).
CLEAR search_results.
" Modern
DATA(ld_start) = 0.
DO.
DATA(ld_position) = find( val = search_string
pcre = `\w*is\w*`
off = ld_start ).
IF ld_position = -1.
EXIT.
ENDIF.
DATA(ld_to) = find_end( val = search_string
pcre = `\w*is\w*`
off = ld_start ).
INSERT substring( val = search_string
off = ld_position
len = ld_to - ld_position ) INTO TABLE search_results.
ld_start = ld_to.
ENDDO.
out->write( `Modern:` ).
out->write( search_results ).
" XCO
search_results = xco_cp=>string( search_string )->grep(
iv_regular_expression = `\w*is\w*`
io_engine = xco_cp_regular_expression=>engine->pcre( )
)->value.
out->write( `XCO:` ).
out->write( search_results ).
ENDMETHOD.
METHOD validate_string.
DATA(regex) = xco_cp=>regular_expression( iv_value = `^[A-Z0-9_]+$`
io_engine = xco_cp_regular_expression=>engine->pcre( ) ).
IF regex->matches( `MY_CONTENT` ).
out->write( 'Match!' ).
ENDIF.
ENDMETHOD.
ENDCLASS.
Fazit
Reguläre Ausdrücke benötigst du recht oft in der Entwicklung, um Eingaben zu validieren, aber auch um zum Beispiel in XSD eine Extraktion von Daten durchzuführen. Die Variante für XCO kann dir etwas an Schreibarbeit abnehmen.
Quelle:
SAP Help - Regular Expression
