ABAP FIND-Anweisung: Zeichenketten und Muster (Regex) suchen

kategorie
ABAP-Statements
Veröffentlicht
autor
Johannes

Die FIND-Anweisung in ABAP wird verwendet, um innerhalb von zeichenartigen Datenobjekten (Variablen vom Typ STRING, C, N, D, T) nach Zeichenketten oder Mustern zu suchen. Sie ist ein sehr flexibles Werkzeug für die Textanalyse und bietet zwei Hauptmodi:

  1. Suche nach einem festen Substring: Findet das exakte Vorkommen einer bestimmten Zeichenkette.
  2. Suche mittels Regulärer Ausdrücke (Regex): Findet Muster, die durch einen regulären Ausdruck (nach PCRE-Standard - Perl Compatible Regular Expressions) beschrieben werden. Dies erlaubt deutlich komplexere und flexiblere Suchen.

Syntax

Die Syntax variiert leicht je nach Modus und den gewünschten Optionen:

1. Allgemeine Struktur

FIND [{FIRST OCCURRENCE}|{ALL OCCURRENCES OF}]
{<substring>}|{REGEX <regex>}
IN [SECTION OFFSET <off> LENGTH <len> OF] <data_object>
[IGNORING CASE|RESPECTING CASE] " Groß-/Kleinschreibung ignorieren/beachten
[MATCH OFFSET <m_off>] " Offset des Fundes speichern
[MATCH LENGTH <m_len>] " Länge des Fundes speichern
[MATCH COUNT <m_cnt>] " Anzahl aller Funde speichern (nur bei ALL OCCURRENCES)
[RESULTS <result_tab>|<result_wa>] " Detaillierte Ergebnisse speichern
[SUBMATCHES <sm1> <sm2> ...]. " Subgruppen bei Regex speichern

2. Syntax für Substring-Suche

FIND [{FIRST OCCURRENCE}|{ALL OCCURRENCES OF}] <substring>
IN <data_object>
[<optionen>]. " z.B. IGNORING CASE, MATCH OFFSET, MATCH LENGTH, MATCH COUNT, RESULTS

3. Syntax für Reguläre Ausdrücke (Regex)

FIND [{FIRST OCCURRENCE}|{ALL OCCURRENCES OF}] REGEX <regex>
IN <data_object>
[<optionen>]. " z.B. IGNORING CASE, MATCH OFFSET, MATCH LENGTH, MATCH COUNT, RESULTS, SUBMATCHES

Erklärung der Schlüsselkomponenten und Optionen

  • FIND: Das Schlüsselwort, das die Anweisung einleitet.
  • FIRST OCCURRENCE: (Standard, wenn nichts angegeben) Sucht nur das erste Vorkommen des Musters von links nach rechts.
  • ALL OCCURRENCES: Sucht alle nicht überlappenden Vorkommen des Musters.
  • <substring>: Eine Variable oder ein Literal mit dem exakten Text, nach dem gesucht wird (im Substring-Modus).
  • REGEX <regex>: Eine Variable oder ein Literal, das einen Regulären Ausdruck enthält (im Regex-Modus).
  • IN <data_object>: Das zeichenartige Datenobjekt (STRING, C, N, D, T), in dem gesucht werden soll.
  • IN SECTION OFFSET <off> LENGTH <len> OF: Schränkt die Suche auf einen bestimmten Abschnitt innerhalb von <data_object> ein (beginnend bei Offset <off> mit Länge <len>; der erste Offset ist 0).
  • IGNORING CASE: Führt die Suche ohne Berücksichtigung der Groß-/Kleinschreibung durch.
  • RESPECTING CASE: (Standard) Führt die Suche mit Berücksichtigung der Groß-/Kleinschreibung durch.
  • MATCH OFFSET <m_off>: Weist der Variablen <m_off> (Typ I) den Start-Offset (Position, 0-basiert) des gefundenen Musters zu.
  • MATCH LENGTH <m_len>: Weist der Variablen <m_len> (Typ I) die Länge des gefundenen Musters zu.
  • MATCH COUNT <m_cnt>: (Nur mit ALL OCCURRENCES) Weist der Variablen <m_cnt> (Typ I) die Gesamtzahl der gefundenen Vorkommen zu.
  • RESULTS <result_tab | result_wa>: Speichert detaillierte Informationen über die Funde.
    • Bei ALL OCCURRENCES: <result_tab> (Typ match_result_tab oder kompatibel) wird mit Informationen zu allen Funden gefüllt (Offset, Länge, Submatch-Offsets und -Längen bei Regex).
    • Bei FIRST OCCURRENCE: <result_wa> (Typ match_result oder kompatibel) wird mit den Informationen zum **ersten ** Fund gefüllt.
  • SUBMATCHES <sm1> <sm2> ...: (Nur mit REGEX) Wenn der reguläre Ausdruck geklammerte Gruppen (Capture Groups) enthält, wird der von der ersten Gruppe gefundene Text in <sm1>, der von der zweiten in <sm2> usw. gespeichert ( Variablen meist vom Typ STRING).

Systemfelder

sy-subrc: Zeigt das Ergebnis der Suche an:

  • 0: Erfolgreich (mindestens ein Vorkommen gefunden).
  • 4: Nicht erfolgreich (kein Vorkommen gefunden).
  • 8: Fehler (z. B. ungültiger Regex bei bestimmten Zusätzen). sy-fdpos: Enthält nach einer erfolgreichen Suche (sy-subrc = 0) den Offset des zuletzt gefundenen Vorkommens relativ zum Anfang von <data_object>.

Beispiele

1. Erstes Vorkommen eines Substrings finden

DATA text TYPE string VALUE `Das ist ein Beispieltext. Beispielhaft!`.
DATA position TYPE i.
FIND 'Beispiel' IN text MATCH OFFSET position.
IF sy-subrc = 0.
WRITE: / 'Substring "Beispiel" gefunden an Position (Offset):', position. " Ausgabe: ... an Position (Offset): 12
ELSE.
WRITE: / 'Substring "Beispiel" nicht gefunden.'.
ENDIF.

2. Alle Vorkommen zählen (Case-Insensitiv)

DATA anzahl TYPE i.
FIND ALL OCCURRENCES OF 'beispiel' IN text IGNORING CASE MATCH COUNT anzahl.
IF sy-subrc = 0.
WRITE: / '"beispiel" (ohne Groß/Kleinschreibung) wurde', anzahl, 'Mal gefunden.'. " Ausgabe: ... 2 Mal gefunden.
ENDIF.

3. Erstes Vorkommen mit Regex (z. B. eine Zahl finden)

DATA text2 TYPE string VALUE `Bestellung 4711 vom 20.04.2025 enthält 15 Positionen.`.
DATA rx_number TYPE string VALUE `\b\d+\b`. " Regex für eine oder mehrere Ziffern (als Wort)
DATA first_num_off TYPE i.
DATA first_num_len TYPE i.
FIND REGEX rx_number IN text2
MATCH OFFSET first_num_off
MATCH LENGTH first_num_len.
IF sy-subrc = 0.
WRITE: / 'Erste Zahl gefunden:', text2+first_num_off(first_num_len). " Ausgabe: 4711
WRITE: / 'Bei Offset:', first_num_off, ', Länge:', first_num_len. " Ausgabe: Bei Offset: 11 , Länge: 4
ENDIF.

4. Alle Vorkommen mit Regex und RESULTS-Tabelle

DATA match_results TYPE match_result_tab.
FIND ALL OCCURRENCES OF REGEX rx_number IN text2 RESULTS match_results.
IF sy-subrc = 0.
WRITE: / 'Alle gefundenen Zahlen:'.
LOOP AT match_results INTO DATA(match_line).
WRITE: / text2+match_line-offset(match_line-length),
'(Offset:', match_line-offset, 'Länge:', match_line-length, ')'.
ENDLOOP.
" Ausgabe:
" 4711 (Offset: 11 Länge: 4 )
" 20 (Offset: 21 Länge: 2 )
" 04 (Offset: 24 Länge: 2 )
" 2025 (Offset: 27 Länge: 4 )
" 15 (Offset: 42 Länge: 2 )
ENDIF.

5. Regex mit Submatches (Datum extrahieren)

DATA rx_date TYPE string VALUE `(\d{2})\.(\d{2})\.(\d{4})`. " Gruppen für Tag, Monat, Jahr
DATA day TYPE string.
DATA month TYPE string.
DATA year TYPE string.
FIND REGEX rx_date IN text2 SUBMATCHES day month year.
IF sy-subrc = 0.
WRITE: / 'Datum gefunden:'.
WRITE: / 'Tag:', day, 'Monat:', month, 'Jahr:', year. " Ausgabe: Tag: 20 Monat: 04 Jahr: 2025
ENDIF.

6. Suche in einem Abschnitt

DATA name TYPE c LENGTH 30 VALUE 'Hans Peter Mustermann Berlin'.
FIND 'Peter' IN SECTION OFFSET 5 LENGTH 15 OF name.
IF sy-subrc = 0.
WRITE: / '"Peter" gefunden im Abschnitt 5-19, bei Offset:', sy-fdpos. " Ausgabe: ... bei Offset: 5
ELSE.
WRITE: / '"Peter" nicht im Abschnitt 5-19 gefunden.'.
ENDIF.
FIND 'Berlin' IN SECTION OFFSET 5 LENGTH 15 OF name.
IF sy-subrc <> 0.
WRITE: / '"Berlin" nicht im Abschnitt 5-19 gefunden.'. " Ausgabe: "Berlin" nicht im Abschnitt ... gefunden.
ENDIF.

Wichtige Hinweise

  • FIND ist für zeichenartige Datenobjekte konzipiert.
  • Reguläre Ausdrücke sind extrem mächtig, aber ihre Syntax muss gelernt werden (ABAP verwendet PCRE).
  • Die ältere Anweisung SEARCH ist funktional stark eingeschränkt und sollte durch FIND ersetzt werden.
  • Zum Ersetzen von gefundenen Mustern dient die REPLACE-Anweisung, die sehr ähnliche Suchoptionen wie FIND bietet.