Les expressions régulières (Regex) permettent une recherche et un remplacement de motifs complexes dans les chaînes. ABAP supporte les expressions régulières compatibles POSIX via des instructions et des classes.
Possibilités d’utilisation
FIND … REGEX – Rechercher un motif dans une chaîne
REPLACE … REGEX – Remplacer un motif
matches() – Vérifier si une chaîne correspond au motif
cl_abap_regex / cl_abap_matcher – API orientée objet
Aperçu de la syntaxe Regex
Caractère Signification Exemple .N’importe quel caractère a.c → abc, aXc*0 ou plus ab*c → ac, abc, abbc+1 ou plus ab+c → abc, abbc?0 ou 1 ab?c → ac, abc^Début ^Hello$Fin World$[abc]Classe de caractères [aeiou] → Voyelles[^abc]Classe niée [^0-9] → Non-chiffres[a-z]Plage [A-Za-z] → Lettres\dChiffre [0-9] \d{4} → 4 chiffres\wCaractère de mot [a-zA-Z0-9_] \w+\sEspace blanc \s+ → Espaces\bLimite de mot \bword\b{n}Exactement n fois a{3} → aaa{n,m}n à m fois a{2,4} → aa, aaa, aaaa(...)Groupe (ab)+ → ab, abab|Ou cat|dog
Exemples
1. FIND avec 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 : / 'Trouvé:' , lv_number. " 12345
2. Trouver toutes les occurrences (FIND ALL OCCURRENCES)
DATA : lv_text TYPE string VALUE 'Tel: 030-12345, Fax: 040-67890, Mobil: 0170-9876543' .
" Trouver tous les numéros de téléphone
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: / ' Téléphone: ', lv_phone.
" Téléphone: 0170-9876543
DATA : lv_date TYPE string VALUE 'Datum: 2024-11-15' .
" Extraire la date avec des groupes
FIND REGEX '(\d{4})-(\d{2})-(\d{2})"
SUBMATCHES DATA(lv_year) DATA(lv_month) DATA(lv_day).
WRITE: / ' Année: ', lv_year. " 2024
WRITE: / ' Mois: ', lv_month. " 11
WRITE: / ' Jour: ', lv_day. " 15
4. REPLACE avec REGEX
DATA : lv_text TYPE string VALUE 'Preis: 123.45 EUR, Rabatt: 10.00 EUR' .
" Remplacer les nombres par XXX
REPLACE ALL OCCURRENCES OF REGEX '\d+\.?\d*"
WRITE: / lv_text. " Preis: XXX EUR, Rabatt: XXX EUR
5. Références arrière
DATA : lv_text TYPE string VALUE 'Die die Katze sitzt auf auf dem Dach.' .
" Supprimer les mots en double (référence arrière \1)
REPLACE ALL OCCURRENCES OF REGEX '\b(\w+)\s+\1\b"
WRITE: / lv_text. " Die Katze sitzt auf dem Dach.
6. matches() – Vérifier si le motif correspond
" Validation simple d'email
IF matches ( val = lv_email regex = '^\w+@\w+\.\w+$' ).
WRITE : / 'Email invalide' .
" Plusieurs vérifications
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() avec Regex
DATA : lv_text TYPE string VALUE 'Bestellung Nr. 12345 wurde versandt' .
IF contains ( val = lv_text regex = '\d+' ).
WRITE : / 'Le texte contient des nombres' .
IF contains ( val = lv_text regex = '^Bestellung' ).
WRITE : / 'C''est une commande' .
8. count() avec Regex
DATA : lv_text TYPE string VALUE 'a1b2c3d4e5' .
DATA (lv_digit_count) = count ( val = lv_text regex = '\d' ).
WRITE : / 'Nombre de chiffres:' , 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 : / 'Nombre de mots:' , lv_word_count. " 6
9. cl_abap_regex – Orienté objet
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 ).
" Parcourir toutes les correspondances
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 : / 'Correspondance:' , lv_full.
WRITE : / ' Clé:' , lv_key, 'Valeur:' , lv_value.
" Correspondance: Name: Max
" Correspondance: Alter: 30
DATA : lv_text TYPE string VALUE
DATA : lt_emails TYPE string_table.
" Trouver tous les emails
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. Pratique : Nettoyer les données
" Normaliser un numéro de téléphone
DATA : lv_phone TYPE string VALUE '+49 (0) 170 / 123 45 67' .
" Supprimer tous les non-chiffres sauf +
REPLACE ALL OCCURRENCES OF REGEX '[^\d+]' IN lv_phone WITH '' .
WRITE : / lv_phone. " +491701234567
" Réduire les espaces multiples
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. Pratique : Validations
" Valider un IBAN (simplifié)
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 : / 'Format IBAN valide' .
" Valider un code postal (Allemagne)
DATA : lv_plz TYPE string VALUE '12345' .
IF matches ( val = lv_plz regex = '^\d{5}$' ).
WRITE : / 'Code postal allemand valide' .
" Valider une date (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 : / 'Format de date valide' .
13. Pratique : Parsing
" Parser une ligne de log
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: / ' Date: ', lv_date.
WRITE: / ' Heure: ', lv_time.
WRITE: / ' Niveau: ', lv_level.
WRITE: / ' Message: ', lv_message.
14. Pratique : Parsing CSV
DATA : lv_csv TYPE string VALUE 'Max;Mustermann;30;Berlin' .
DATA : lt_fields TYPE string_table.
" Split par point-virgule (alternative à 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 )
" Ou plus simple avec SPLIT:
SPLIT lv_csv AT ';' INTO TABLE lt_fields.
15. Recherche insensible à la casse
DATA : lv_text TYPE string VALUE 'ABAP ist super, abap ist toll' .
" Insensible à la casse avec (?i)
FIND ALL OCCURRENCES OF REGEX '(?i)abap"
MATCH COUNT DATA(lv_count).
WRITE: / ' Trouvé: ', lv_count, ' fois '. " 2
16. Fonction d’échappement
DATA : lv_search TYPE string VALUE 'a.b*c?' .
" Échapper les caractères spéciaux pour une recherche littérale
DATA (lv_escaped) = escape ( val = lv_search format = cl_abap_format=>e_regex ).
WRITE : / 'Échappé:' , lv_escaped. " a\.b\*c\?
" Maintenant lv_escaped peut être utilisé dans REGEX
DATA : lv_text TYPE string VALUE 'Test a.b*c? Ende' .
FIND REGEX lv_escaped IN lv_text.
Motifs Regex courants
Objectif Motif Nombre \d+ ou [0-9]+Nombre décimal \d+\.?\d*Mot \w+ ou [A-Za-z]+Email (simple) [\w.+-]+@[\w.-]+\.\w{2,}URL https?://[\w./%-]+Date (YYYY-MM-DD) \d{4}-\d{2}-\d{2}Code postal (DE) \d{5}Téléphone (DE) (\+49|0)\d{2,4}[-/]?\d+Adresse IP \d{1,3}\.\d{1,3}\.\d{1,3}\.\d{1,3}Supprimer espaces \s+ → “Balises HTML <[^>]+>
Options FIND/REPLACE
FIND REGEX pattern IN text
[ IGNORING CASE ] " Ignorer majuscules/minuscules
[ MATCH OFFSET off ] " Position de début de la correspondance
[ MATCH LENGTH len ] " Longueur de la correspondance
[ MATCH COUNT cnt ] " Nombre de correspondances
[ SUBMATCHES s1 s2 ... ] " Contenus des groupes
[ RESULTS result_tab ]. " Toutes les correspondances sous forme de table
Remarques importantes / Bonnes pratiques
Syntaxe PCRE (compatible Perl) avec cl_abap_regex=>create_pcre().
Le Regex ABAP standard est compatible POSIX .
Utilisez escape() pour échapper les caractères spéciaux.
Submatches avec (...) pour l’extraction de groupes.
(?i) au début pour une recherche insensible à la casse .
Performance : Regex compilée (cl_abap_regex) pour utilisation multiple.
matches() vérifie si la chaîne entière correspond au motif.
contains( ... regex = ...) vérifie si le motif est contenu .
\d, \w, \s sont des formes courtes pour les classes de caractères.
Testez les Regex avec des outils en ligne (regex101.com) avant l’implémentation.