Регулярні вирази (regex) — це мова шаблонів для пошуку, перевірки й заміни в рядках. В ABAP регулярні вирази використовуються у FIND/REPLACE, вбудованих функціях (find, match, replace, contains, substring_* тощо), функціях ABAP SQL/CDS (like_regexpr, replace_regexpr …) і через об’єктне API класів CL_ABAP_REGEX / CL_ABAP_MATCHER.
Основний синтаксис — PCRE (Perl Compatible Regular Expressions). Підтримуються також XPath і XSD (автоматично конвертуються в PCRE). Застаріло: POSIX (REGEX/regex додатки й параметри; краще одразу PCRE/pcre).
Вираз Значення xКонкретний символ .Будь-який символ крім переводу рядка (у dotall mode — будь-який) \d / \DЦифра / не цифра \s / \SWhitespace (пробіл, табуляція, новий рядок) / не whitespace \w / \WСлівний символ (літера, цифра, _) / не слівний \n, \t, \r, \RLF, tab, CR, будь-яка послідовність нового рядка \x{hex}Символ за hex-кодом \p{..} / \P{..}Юнікод-властивість (напр. \p{Ll} — малі літери)
" Замінити всі цифри на #
DATA ( res ) = replace ( val = `a1-b2 3-4c9` pcre = `\d` with = `#` occ = 0 ). " a#-b# #-#c#
" Замінити всі whitespace
res = replace ( val = | ab cd\tef\ngh | pcre = `\s` with = `#` occ = 0 ). " ab#cd#ef#gh
Вираз Значення x*, x+0+ / 1+ повторень (жадібно) x?Опціонально (0 або 1) x{m}, x{m,n}, x{m,}Точно m / від m до n / m і більше x*?, x+?Нежадібні версії x|yАльтернатива: x або y
DATA ( a ) = replace ( val = `<span>Hallo</span>` pcre = `<.+>` with = `#` ). " # (цілий блок)
DATA ( b ) = replace ( val = `<span>Hallo</span>` pcre = `<.+?>` with = `#` ). " #Hallo#
Вираз Значення [abc]Будь-який символ із набору [a-z]Діапазон [^abc]Заперечення — не зі списку [^a-z]Заперечення діапазону
DATA ( r ) = replace ( val = `bit bat but bet` pcre = `b[iu]` with = `#` occ = 0 ). " #t bat #t bet
Вираз Значення \A, \ZПочаток / кінець всього тексту ^, $Початок / кінець рядка (у multi-line mode — кожного рядка) \b, \BМежа слова / не межа \KСкидає стартову позицію збігу (символи до \K не входять у match)
" Знайти останню кому й усе після неї (\K виключає кому)
FIND PCRE `,(?!.*,)\K.*` IN str MATCH OFFSET DATA ( off ) MATCH LENGTH DATA ( len ).
Вираз Значення (...)Capturing group (?<name>...), (?'name'...)Іменована група (?:...)Non-capturing group \1, \2Back-reference на n-ту групу $0, $1, ${name}Посилання в заміні ($0 — увесь збіг)
" Переставити пари: APAB → ABAP
DATA ( s ) = replace ( val = `APAB` pcre = `(..)(..)` with = `$2$1` ).
" Іменовані групи: YYYYMMDD → DD.MM.YYYY
pcre = `(?<yr>\d{4})(?<mo>\d{2})(?<d>\d{2})`
with = `${d}.${mo}.${yr}` ). " 28.11.2024
Вираз Значення (?=...)Позитивний lookahead — далі є патерн (?!...)Негативний lookahead — далі немає (?<=...)Позитивний lookbehind — перед є патерн (?<!...)Негативний lookbehind
DATA ( r ) = replace ( val = `ab c abcd` pcre = `(?<=\s)c` with = `#` occ = 0 ). " ab # abcd
" 'a', за якою НЕ йде 'b'
r = replace ( val = `abc ade` pcre = `a(?!b)` with = `#` occ = 0 ). " abc #de
Опція Значення (?i)Ignore case (?m)Multi-line (^/$ на кожному рядку) (?s)Single-line / dotall (. матчить \n) (?-x)Вимкнути extended mode (*UTF)Увімкнути UTF mode (*CR), (*LF), (*CRLF), (*ANYCRLF)Тип перенесення рядка
Грабля: extended mode за замовчуванням
ABAP PCRE — у extended mode, тобто неекранований пробіл у патерні ігнорується . Щоб матчити пробіл, пишіть \s, \ або вимкніть режим через (?-x).
" Extended mode: пробіл у патерні ігнорується
DATA ( a ) = replace ( val = `abc def` pcre = `abc def` with = `#` ). " НЕ замінить
DATA ( b ) = replace ( val = `abc def` pcre = `abc\sdef` with = `#` ). " #
DATA ( c ) = replace ( val = `abc def` pcre = `(?-x)abc def` with = `#` ). " #
Маркер Дія \uПерший символ — uppercase \UУсе — uppercase до \L/\E \l / \LТе саме для lowercase \EЗавершити трансформацію
DATA ( r ) = replace ( val = `abcdefg` pcre = `c(.*)` with = `c\U$1` ). " abcDEFG
r = replace ( val = `abcdefg` pcre = `c(..)(..)` with = `c\U$1\E$2` ). " abcDEfg
FIND і REPLACE з додатком PCRE. Корисні додатки: ALL OCCURRENCES, MATCH COUNT, RESULTS, SUBMATCHES, MATCH OFFSET/LENGTH, IN TABLE, IGNORING CASE, FROM ... TO ..., REPLACEMENT COUNT.
DATA ( str ) = `Cathy's black cat on the mat played with Matt.` .
FIND ALL OCCURRENCES OF PCRE `[A-Za-z]` IN str MATCH COUNT DATA ( n ).
" Усі входження з позиціями в таблицю match_result_tab
FIND ALL OCCURRENCES OF PCRE `\s` IN str RESULTS DATA ( res ).
" SUBMATCHES — витягти групи напряму
FIND PCRE `(.*)\son\s(.*)` IN str IGNORING CASE SUBMATCHES DATA ( left ) DATA ( right ).
REPLACE ALL OCCURRENCES OF PCRE `p.` IN str WITH `#`
REPLACEMENT COUNT DATA ( cnt ) RESULTS DATA ( repl_res ).
Пошук у внутрішній таблиці (тип рядка має бути character-like):
DATA ( itab ) = VALUE string_table( ( `abc` ) ( `def` ) ( `ghi` ) ).
FIND ALL OCCURRENCES OF PCRE `\w` IN TABLE itab RESULTS DATA ( tab_res ).
REPLACE ALL OCCURRENCES OF PCRE `\d` IN TABLE itab FROM 1 TO 2 WITH `#` .
Приймають параметр pcre замість sub. Параметр occ вказує номер входження (0 — усі для replace).
DATA ( text ) = `Pieces of cakes.` .
DATA ( p1 ) = find ( val = text pcre = `\.` ). " 15
DATA ( p2 ) = find_end ( val = text pcre = `\s` ). " 7
DATA ( c ) = count ( val = text pcre = `\s` ). " 2
" match — повертає сам збіг
DATA ( email ) = match ( val = `Write to jon.doe@email.com please`
pcre = `\w+(\.\w+)*@(\w+\.)+(\w{2,4})` ). " jon.doe@email.com
text = `Lorem ipsum dolor sit amet` .
DATA ( sa ) = substring_after ( val = text pcre = `\s` occ = 2 ). " dolor sit amet
DATA ( sb ) = substring_before ( val = text pcre = `\s` occ = 2 ). " Lorem ipsum
DATA ( ok ) = xsdbool ( matches ( val = `jon.doe@email.com`
pcre = `\w+(\.\w+)*@(\w+\.)+(\w{2,4})` ) ).
Для SQL/CDS — окремі функції (використовують PCRE1 у HANA).
Функція Призначення like_regexpr( pcre = ... value = ... )1/0 — знайдено чи ніlocate_regexpr / locate_regexpr_afterOffset збігу (початок / після) occurrences_regexprКількість входжень replace_regexprЗаміна substring_regexprПідрядок за патерном
like_regexpr ( pcre = '\..' , value = url ) AS has_dot,
locate_regexpr ( pcre = '\..' , value = url, occurrence = 2 ) AS pos_2nd,
occurrences_regexpr ( pcre = '\..' , value = url ) AS n_matches,
replace_regexpr ( pcre = '\..' , value = url, with = '#' ) AS url_masked,
substring_regexpr ( pcre = '\...' , value = url ) AS fragment
Для багаторазового використання шаблону або складнішої обробки — об’єктне API.
CL_ABAP_REGEX — об’єктне представлення regex. Метод create_pcre створює інстанс із PCRE-шаблоном. Параметри: ignore_case, extended, enable_multiline, table тощо.
CL_ABAP_MATCHER — застосовує regex до рядка або таблиці. Методи: find_all, find_next, replace_all, get_match, get_offset, get_length, get_submatch, set_callout.
DATA ( str ) = `a1 # B2 ? cd . E3` .
" Створити regex і matcher
DATA ( regex ) = cl_abap_regex=>create_pcre( pattern = `\D\d` ignore_case = abap_true ).
DATA ( matcher ) = regex->create_matcher( text = str ).
DATA ( matcher2 ) = cl_abap_matcher=>create_pcre( pattern = `\D\d`
ignore_case = abap_true ).
DATA ( all ) = matcher->find_all( ). " type match_result_tab
" Послідовний обхід через find_next
DATA strtab TYPE string_table.
WHILE matcher2->find_next( ) = abap_true .
DATA ( off ) = matcher2->get_offset( ).
DATA ( len ) = matcher2->get_length( ).
APPEND |{ off } : { len } { str+off(len) }| TO strtab.
DATA ( cnt ) = matcher2->replace_all( newtext = `#$1#` ).
DATA ( out ) = matcher2->text.
Пошук у таблиці через matcher :
DATA ( tab ) = VALUE string_table( ( `abZdez` ) ( `zZfghZ` ) ( `ijkZZz` ) ).
DATA ( m ) = cl_abap_matcher=>create_pcre( pattern = `z+`
ignore_case = abap_true ).
m->replace_all( newtext = `#` ).
DATA ( tab_out ) = m->table.
Multiline / extended параметри :
" Multi-line: ^ матчить початок кожного рядка
DATA ( mm ) = cl_abap_matcher=>create_pcre( pattern = `^`
enable_multiline = abap_true ).
mm->replace_all( newtext = `#` ). " #abc\n#def\n#ghi
" Вимкнути extended — пробіли враховуються
DATA ( me ) = cl_abap_matcher=>create_pcre( pattern = `abc def`
me->replace_all( newtext = `#` ). " #
Порада: reuse через CL_ABAP_REGEX
Якщо той самий шаблон застосовується до багатьох рядків у циклі, створіть один cl_abap_regex і використовуйте create_matcher( text = ... ) для кожного тексту — компіляція шаблону виконується лише раз.
Задача Рішення Разова перевірка формату matches( val = ... pcre = ... )Перший збіг як рядок match( ... )Заміна всіх входжень replace( ... occ = 0 ) або REPLACE ALL OCCURRENCES OF PCREПозиції всіх збігів FIND ALL OCCURRENCES OF PCRE ... RESULTS ...Витяг груп SUBMATCHES DATA(...) або RESULTS зі submatchesРегулярка в SQL *_regexpr функції ABAP SQL/CDSСкладна обробка з callbacks CL_ABAP_REGEX + CL_ABAP_MATCHER + set_calloutReuse шаблону в циклі Один cl_abap_regex, багато create_matcher
Виняток Коли CX_SY_INVALID_REGEXНевалідний синтаксис patterns CX_SY_INVALID_REGEX_FORMATНевалідне посилання в replacement (напр. $2 без групи 2) CX_SY_REGEX_TOO_COMPLEXНадто складний regex (обмеження рушія)
Адаптовано з 28_Regular_Expressions.md (Apache 2.0).