Regular Expressions (Regex) ermöglichen komplexe Mustersuche und -ersetzung in Strings. ABAP unterstützt POSIX-kompatible reguläre Ausdrücke über Statements und Klassen.
Verwendungsmöglichkeiten
FIND … REGEX – Muster in String suchen
REPLACE … REGEX – Muster ersetzen
matches() – Prüfen ob String dem Muster entspricht
cl_abap_regex / cl_abap_matcher – Objektorientierte API
Regex-Syntax Übersicht
Zeichen Bedeutung Beispiel .Beliebiges Zeichen a.c → abc, aXc*0 oder mehr ab*c → ac, abc, abbc+1 oder mehr ab+c → abc, abbc?0 oder 1 ab?c → ac, abc^Anfang ^Hello$Ende World$[abc]Zeichenklasse [aeiou] → Vokale[^abc]Negierte Klasse [^0-9] → Nicht-Ziffern[a-z]Bereich [A-Za-z] → Buchstaben\dZiffer [0-9] \d{4} → 4 Ziffern\wWortzeichen [a-zA-Z0-9_] \w+\sWhitespace \s+ → Leerzeichen\bWortgrenze \bword\b{n}Genau n-mal a{3} → aaa{n,m}n bis m-mal a{2,4} → aa, aaa, aaaa(...)Gruppe (ab)+ → ab, abab|Oder cat|dog
Beispiele
1. FIND mit REGEX
DATA : lv_text TYPE string VALUE 'Bestellung 12345 vom 2024-11-15' .
FIND REGEX '\d+' IN lv_text MATCH OFFSET DATA (lv_offset)
MATCH LENGTH DATA (lv_length).
DATA (lv_number) = substring ( val = lv_text off = lv_offset len = lv_length ).
WRITE : / 'Gefunden:' , lv_number. " 12345
2. Alle Treffer finden (FIND ALL OCCURRENCES)
DATA : lv_text TYPE string VALUE 'Tel: 030-12345, Fax: 040-67890, Mobil: 0170-9876543' .
" Alle Telefonnummern finden
FIND ALL OCCURRENCES OF REGEX '\d{3,4}-\d+'
RESULTS DATA (lt_results).
LOOP AT lt_results INTO DATA (ls_result).
DATA (lv_phone) = substring ( val = lv_text
len = ls_result-length ).
WRITE : / 'Telefon:' , lv_phone.
DATA : lv_date TYPE string VALUE 'Datum: 2024-11-15' .
" Datum mit Gruppen extrahieren
FIND REGEX '(\d{4})-(\d{2})-(\d{2})'
SUBMATCHES DATA (lv_year) DATA (lv_month) DATA (lv_day).
WRITE : / 'Jahr:' , lv_year. " 2024
WRITE : / 'Monat:' , lv_month. " 11
WRITE : / 'Tag:' , lv_day. " 15
4. REPLACE mit REGEX
DATA : lv_text TYPE string VALUE 'Preis: 123.45 EUR, Rabatt: 10.00 EUR' .
" Zahlen durch XXX ersetzen
REPLACE ALL OCCURRENCES OF REGEX '\d+\.?\d*'
WRITE : / lv_text. " Preis: XXX EUR, Rabatt: XXX EUR
5. Rückwärtsreferenzen
DATA : lv_text TYPE string VALUE 'Die die Katze sitzt auf auf dem Dach.' .
" Doppelte Wörter entfernen (Rückwärtsreferenz \1)
REPLACE ALL OCCURRENCES OF REGEX '\b(\w+)\s+\1\b'
WRITE : / lv_text. " Die Katze sitzt auf dem Dach.
6. matches() – Prüfen ob Pattern passt
DATA : lv_email TYPE string VALUE 'test@example.com' .
" Einfache E-Mail-Validierung
IF matches ( val = lv_email regex = '^\w+@\w+\.\w+$' ).
WRITE : / 'Gültige E-Mail' .
WRITE : / 'Ungültige E-Mail' .
DATA : lv_phone TYPE string VALUE '+49-170-1234567' .
DATA (lv_valid_phone) = xsdbool (
matches ( val = lv_phone regex = '^\+?\d{2,3}-\d{2,4}-\d{4,}$' )
7. contains() mit Regex
DATA : lv_text TYPE string VALUE 'Bestellung Nr. 12345 wurde versandt' .
IF contains ( val = lv_text regex = '\d+' ).
WRITE : / 'Text enthält Zahlen' .
IF contains ( val = lv_text regex = '^Bestellung' ).
WRITE : / 'Ist eine Bestellung' .
8. count() mit Regex
DATA : lv_text TYPE string VALUE 'a1b2c3d4e5' .
DATA (lv_digit_count) = count ( val = lv_text regex = '\d' ).
WRITE : / 'Anzahl Ziffern:' , lv_digit_count. " 5
DATA : lv_sentence TYPE string VALUE 'Dies ist ein Beispielsatz mit Wörtern' .
DATA (lv_word_count) = count ( val = lv_sentence regex = '\b\w+\b' ).
WRITE : / 'Anzahl Wörter:' , lv_word_count. " 6
9. cl_abap_regex – Objektorientiert
DATA : lv_text TYPE string VALUE 'Name: Max Mustermann, Alter: 30' .
DATA (lo_regex) = cl_abap_regex=>create_pcre( pattern = '(\w+):\s*(\S+)' ).
DATA (lo_matcher) = lo_regex->create_matcher( text = lv_text ).
" Alle Treffer durchlaufen
WHILE lo_matcher->find_next( ).
DATA (lv_full) = lo_matcher->get_match( ).
DATA (lv_key) = lo_matcher->get_submatch( 1 ).
DATA (lv_value) = lo_matcher->get_submatch( 2 ).
WRITE : / 'Match:' , lv_full.
WRITE : / ' Key:' , lv_key, 'Value:' , lv_value.
DATA : lv_text TYPE string VALUE
'Kontakt: info@firma.de, support@firma.de oder sales@firma.de' .
DATA : lt_emails TYPE string_table.
FIND ALL OCCURRENCES OF REGEX '[\w.+-]+@[\w.-]+\.\w{2,}'
RESULTS DATA (lt_results).
LOOP AT lt_results INTO DATA (ls_result).
APPEND substring ( val = lv_text
len = ls_result-length ) TO lt_emails.
LOOP AT lt_emails INTO DATA (lv_email).
11. Praktisch: Daten bereinigen
" Telefonnummer normalisieren
DATA : lv_phone TYPE string VALUE '+49 (0) 170 / 123 45 67' .
" Alle Nicht-Ziffern außer + entfernen
REPLACE ALL OCCURRENCES OF REGEX '[^\d+]' IN lv_phone WITH '' .
WRITE : / lv_phone. " +491701234567
" Mehrfache Leerzeichen reduzieren
DATA : lv_text TYPE string VALUE 'Zu viele Leerzeichen hier' .
REPLACE ALL OCCURRENCES OF REGEX '\s{2,}' IN lv_text WITH ' ' .
WRITE : / lv_text. " Zu viele Leerzeichen hier
12. Praktisch: Validierungen
" IBAN validieren (vereinfacht)
DATA : lv_iban TYPE string VALUE 'DE89370400440532013000' .
IF matches ( val = lv_iban regex = '^[A-Z]{2}\d{2}[A-Z0-9]{4}\d{7}([A-Z0-9]?){0,16}$' ).
WRITE : / 'Gültiges IBAN-Format' .
" PLZ validieren (Deutschland)
DATA : lv_plz TYPE string VALUE '12345' .
IF matches ( val = lv_plz regex = '^\d{5}$' ).
WRITE : / 'Gültige deutsche PLZ' .
" Datum validieren (YYYY-MM-DD)
DATA : lv_date TYPE string VALUE '2024-11-15' .
IF matches ( val = lv_date regex = '^\d{4}-(0[1-9]|1[0-2])-(0[1-9]|[12]\d|3[01])$' ).
WRITE : / 'Gültiges Datumsformat' .
13. Praktisch: Parsing
DATA : lv_log TYPE string VALUE '2024-11-15 10:30:45 [ERROR] Database connection failed' .
FIND REGEX '^(\d{4}-\d{2}-\d{2})\s+(\d{2}:\d{2}:\d{2})\s+\[(\w+)\]\s+(.+)$'
SUBMATCHES DATA (lv_date) DATA (lv_time) DATA (lv_level) DATA (lv_message).
WRITE : / 'Datum:' , lv_date.
WRITE : / 'Zeit:' , lv_time.
WRITE : / 'Level:' , lv_level.
WRITE : / 'Nachricht:' , lv_message.
14. Praktisch: CSV-Parsing
DATA : lv_csv TYPE string VALUE 'Max;Mustermann;30;Berlin' .
DATA : lt_fields TYPE string_table.
" Split by Semikolon (alternative zu SPLIT)
FIND ALL OCCURRENCES OF REGEX '[^;]+' IN lv_csv RESULTS DATA (lt_matches).
LOOP AT lt_matches INTO DATA (ls_match).
APPEND substring ( val = lv_csv off = ls_match-offset len = ls_match-length )
" Oder einfacher mit SPLIT:
SPLIT lv_csv AT ';' INTO TABLE lt_fields.
15. Case-Insensitive Suche
DATA : lv_text TYPE string VALUE 'ABAP ist super, abap ist toll' .
" Case-insensitive mit (?i)
FIND ALL OCCURRENCES OF REGEX '(?i)abap'
MATCH COUNT DATA (lv_count).
WRITE : / 'Gefunden:' , lv_count, 'mal' . " 2
16. Escape-Funktion
DATA : lv_search TYPE string VALUE 'a.b*c?' .
" Sonderzeichen escapen für literale Suche
DATA (lv_escaped) = escape ( val = lv_search format = cl_abap_format=>e_regex ).
WRITE : / 'Escaped:' , lv_escaped. " a\.b\*c\?
" Jetzt kann lv_escaped in REGEX verwendet werden
DATA : lv_text TYPE string VALUE 'Test a.b*c? Ende' .
FIND REGEX lv_escaped IN lv_text.
Häufige Regex-Patterns
Zweck Pattern Zahl \d+ oder [0-9]+Dezimalzahl \d+\.?\d*Wort \w+ oder [A-Za-z]+E-Mail (einfach) [\w.+-]+@[\w.-]+\.\w{2,}URL https?://[\w./%-]+Datum (YYYY-MM-DD) \d{4}-\d{2}-\d{2}PLZ (DE) \d{5}Telefon (DE) (\+49|0)\d{2,4}[-/]?\d+IP-Adresse \d{1,3}\.\d{1,3}\.\d{1,3}\.\d{1,3}Leerzeichen entfernen \s+ → “HTML-Tags <[^>]+>
FIND/REPLACE Optionen
FIND REGEX pattern IN text
[ IGNORING CASE ] " Groß-/Kleinschreibung ignorieren
[ MATCH OFFSET off ] " Startposition des Treffers
[ MATCH LENGTH len ] " Länge des Treffers
[ MATCH COUNT cnt ] " Anzahl der Treffer
[ SUBMATCHES s1 s2 ... ] " Gruppeninhalte
[ RESULTS result_tab ]. " Alle Treffer als Tabelle
Wichtige Hinweise / Best Practice
PCRE-Syntax (Perl-kompatibel) mit cl_abap_regex=>create_pcre().
Standard ABAP Regex ist POSIX-kompatibel .
escape() verwenden um Sonderzeichen zu escapen .
Submatches mit (...) für Gruppenextraktion.
(?i) am Anfang für case-insensitive Suche.
Performance : Kompilierte Regex (cl_abap_regex) bei Mehrfachverwendung.
matches() prüft ob gesamter String dem Muster entspricht.
contains( ... regex = ...) prüft ob Muster enthalten ist.
\d, \w, \s sind Kurzformen für Zeichenklassen.
Testen Sie Regex mit Online-Tools (regex101.com) vor der Implementierung.