Difference between revisions of "SAP ABAP REGEX"
From SapWiki
| (35 intermediate revisions by the same user not shown) | |||
| Line 1: | Line 1: | ||
| + | ==PCRE (Perl Compatible Regular Expressions)== | ||
| + | In modern ABAP (SAP NetWeaver 7.55 and higher), using the REPLACE FIRST OCCURRENCE OF REGEX statement triggers a syntax warning because POSIX-style regular expressions are obsolete. The ABAP compiler flags standard inline regex strings in these older statements as deprecated. | ||
| + | |||
| + | ===Ejemplo 1=== | ||
| + | <nowiki> | ||
| + | data: sub1 TYPE c LENGTH 80, | ||
| + | sub2 TYPE c LENGTH 80, | ||
| + | sub3 TYPE c LENGTH 80, | ||
| + | sub4 TYPE c LENGTH 80, | ||
| + | sub5 TYPE c LENGTH 80, | ||
| + | sub6 TYPE c LENGTH 80. | ||
| + | DATA lv_text TYPE string. | ||
| + | |||
| + | lv_text = sy-datlo. | ||
| + | |||
| + | " Create a PCRE-compliant regex object | ||
| + | DATA(lo_regex) = cl_abap_regex=>create_pcre( pattern = '(\d{4})(\d{2})(\d{2})' ). | ||
| + | |||
| + | REPLACE REGEX lo_regex IN lv_text WITH '$3/$2/$1'. | ||
| + | |||
| + | lv_text = sy-datlo. | ||
| + | |||
| + | FIND REGEX lo_regex IN lv_text SUBMATCHES sub1 sub2 sub3. | ||
| + | |||
| + | </nowiki> | ||
| + | ===Ejemplo REPLACE_REGEXPR en CDS view=== | ||
| + | <nowiki> | ||
| + | @AccessControl.authorizationCheck: #NOT_REQUIRED | ||
| + | define view entity demo_cds_sql_func_string_ve | ||
| + | as select from demo_expressions | ||
| + | { | ||
| + | length( char1 ) as r_length, | ||
| + | instr( char1, 'CD' ) as r_instr, | ||
| + | concat( char1, char2 ) as r_concat, | ||
| + | concat_with_space( char1, char2, 10 ) as r_concat_with_space, | ||
| + | left( char1, 3 ) as r_left, | ||
| + | lower( char1 ) as r_lower, | ||
| + | right( char2, 3 ) as r_right, | ||
| + | lpad( char1, 10, 'x' ) as r_lpad, | ||
| + | rpad( char2, 10, 'y' ) as r_rpad, | ||
| + | ltrim( char1, 'A' ) as r_ltrim, | ||
| + | rtrim( char1, 'E' ) as r_rtrim, | ||
| + | replace_regexpr( pcre => '\\Cg', | ||
| + | value => char2, | ||
| + | with => 'bb', | ||
| + | result_length => 4 ) as r_replace_regexpr, | ||
| + | replace( char2, 'ghi', 'XXX' ) as r_replace, | ||
| + | substring( char2, 2, 3 ) as r_substring, | ||
| + | upper( char2 ) as r_upper | ||
| + | } | ||
| + | </nowiki> | ||
| + | |||
== Ejemplos REGEX== | == Ejemplos REGEX== | ||
===Ejemplo de Uso de regex en ABAP=== | ===Ejemplo de Uso de regex en ABAP=== | ||
| − | <nowiki> DATA: lt_match_result TYPE match_result_tab. | + | <nowiki>DATA: lt_match_result TYPE match_result_tab. |
| − | + | data: l_regex type string, | |
| − | + | l_string type string. | |
| − | + | data: l_matches TYPE i. | |
| − | + | l_regex = '^[^<>()\[\]\\,;:\s@"`]+@([a-zA-Z\-0-9]+\.)+[a-zA-Z]{2,}$'. | |
| − | + | l_string = 'pablo.tapia@sapwiki.cl'. | |
| − | + | FIND ALL OCCURRENCES OF REGEX l_regex IN l_string | |
| − | + | IN CHARACTER MODE RESPECTING CASE | |
| − | + | MATCH COUNT l_matches RESULTS lt_match_result. | |
| − | + | if l_matches le 0. | |
| − | + | message i000(0k) with 'E-mail no valido' display like 'E'. | |
| − | + | return. | |
| − | + | endif.</nowiki> | |
===validar rut (muy simple)=== | ===validar rut (muy simple)=== | ||
| Line 25: | Line 77: | ||
===validar Números=== | ===validar Números=== | ||
| + | <nowiki>validar número | ||
| + | 1.1111 correcto | ||
| + | -1.1111 correcto | ||
| + | 1.11111- correcto | ||
| + | 1111 correcto | ||
| + | |||
| + | ^[-?0-9]+([.])?([0-9]+)?-?$ | ||
| + | |||
| + | números de 2 enteros y 7 decimales | ||
| + | 1.1234567 correcto | ||
| + | 11.1234560 correcto | ||
| − | + | ^[0-9]{1,2}\.([0-9]{7})+$ | |
| − | |||
| − | |||
| − | |||
| − | |||
| − | + | con signo izquierda | |
| + | -1.1234567 correcto | ||
| + | 1.1234567 correcto | ||
| − | + | ^-?[0-9]{1,2}\.([0-9]{7})+$ | |
| − | |||
| − | |||
| − | + | con signo derecha o izquierda | |
| + | ^-?[0-9]{1,2}\.([0-9]{7})+-?$ | ||
| − | + | validar número entero | |
| − | + | ^[0-9]+$ | |
| − | |||
| − | + | numero NNN.NN | |
| + | valido | ||
| + | 111.1 | ||
| + | 11.11 | ||
| + | 1 | ||
| − | + | ^\d{1,3}(\.\d{1,2})?$ | |
| − | |||
| − | + | numero entero con máximo de 13 caracteres | |
| − | + | valido | |
| + | 1234567890111 | ||
| + | 111 | ||
| + | 1 | ||
| − | + | ^\d{1,13}$ | |
| − | |||
| − | |||
| − | |||
| − | |||
| − | + | MODULE verificar_folio INPUT. | |
| + | DATA l_string TYPE string. | ||
| + | DATA l_folio(7) TYPE n. | ||
| − | + | IF zfi_datoscajas-folio IS NOT INITIAL. | |
| − | + | MOVE zfi_datoscajas-folio TO l_string. | |
| − | + | CONDENSE l_string. | |
| − | |||
| − | |||
| − | + | FIND REGEX '[^\d]' IN l_string IN CHARACTER MODE RESPECTING CASE. | |
| + | IF sy-subrc = 0. | ||
| + | MESSAGE e000(0k) WITH 'Folio deber contener solo números'. | ||
| + | ELSE. | ||
| + | MOVE l_string TO l_folio. | ||
| + | MOVE l_folio TO zfi_datoscajas-folio. | ||
| + | ENDIF. | ||
| + | ENDIF. | ||
| + | ENDMODULE. | ||
| + | </nowiki> | ||
=== Elimina prefijo === | === Elimina prefijo === | ||
| − | * NC00000009 -> 00000009 | + | <nowiki>* NC00000009 -> 00000009 |
| − | + | *saca prefijos de XBLNR | |
| − | + | data l_xblnr type string. | |
| − | + | l_xblnr = vbrk-xblnr. | |
| − | + | REPLACE all OCCURRENCES OF REGEX '[[:alpha:]]' IN l_xblnr with ''. | |
| − | + | if sy-subrc = 0. | |
| − | + | .... | |
| − | + | endif.</nowiki> | |
ejemplo 2 | ejemplo 2 | ||
| Line 85: | Line 155: | ||
===convertir fecha (yyyymmdd->dd/mm/yyyy)=== | ===convertir fecha (yyyymmdd->dd/mm/yyyy)=== | ||
| − | <nowiki> data l_fecha(10). | + | <nowiki>data l_fecha(10). |
| − | + | l_fecha = sy-datum. | |
| − | + | replace FIRST OCCURRENCE OF REGEX '(\d{4})(\d{2})(\d{2})' | |
| − | in l_fecha WITH '$3/$2/$1'.</nowiki> | + | in l_fecha WITH '$3/$2/$1'. |
| − | + | write:/ l_fecha.</nowiki> | |
| + | |||
| + | ===convertir TIMESTAMP=== | ||
| + | DD.MM.YYYY HORA => YYYY-MM-DD HORA Ejemplo: 03.10.2025 14:55:44 => 2025-10-03 14:55:44 | ||
| + | <nowiki> | ||
| + | FORM get_timestamp CHANGING ev_timestamp TYPE string. | ||
| + | DATA: lv_short_timestamp TYPE timestamp. | ||
| + | DATA lv_timestamp(30). | ||
| + | |||
| + | GET TIME STAMP FIELD lv_short_timestamp. | ||
| + | |||
| + | WRITE lv_short_timestamp TO lv_timestamp TIME ZONE sy-zonlo. | ||
| + | REPLACE FIRST OCCURRENCE OF REGEX '(\d{2})\.(\d{2})\.(\d{4})\s(.*)' | ||
| + | IN lv_timestamp WITH '$3-$2-$1 $4'. | ||
| + | |||
| + | MOVE lv_timestamp TO ev_timestamp. | ||
| + | |||
| + | ENDFORM. | ||
| + | </nowiki> | ||
| + | |||
| + | ===Convierte folio=== | ||
| + | <nowiki>* Folio1: PRmmaaRppnnnnnn | ||
| + | * Folio2: 0208020 + aa + mm + nnnnnn | ||
| + | * Ejemplo: PR0720R007188233 se convierte en 02080202007188233 | ||
| + | |||
| + | *----------------------------------------------------------------------* | ||
| + | * --> p1 text | ||
| + | * <-- p2 text | ||
| + | *----------------------------------------------------------------------* | ||
| + | FORM conv_folio USING p_xblnr TYPE bsis-xblnr | ||
| + | CHANGING p_folio TYPE ze_folio. | ||
| + | |||
| + | DATA l_string TYPE string. | ||
| + | |||
| + | CLEAR p_folio. | ||
| + | |||
| + | l_string = p_xblnr. | ||
| + | REPLACE FIRST OCCURRENCE OF REGEX '(.{2})(.{2})(.{2})(.{1})(.{1})(.{2})(.{6})' | ||
| + | IN l_string WITH '0208020$3$2$7'. | ||
| + | IF sy-subrc = 0. | ||
| + | p_folio = l_string. | ||
| + | ENDIF. | ||
| + | |||
| + | ENDFORM.</nowiki> | ||
===usar REGEX como IF=== | ===usar REGEX como IF=== | ||
ejemplo para verificar por clase de entrega | ejemplo para verificar por clase de entrega | ||
| − | <nowiki> data l_lfart type string. | + | <nowiki>data l_lfart type string. |
| − | + | l_lfart = likp-lfart. | |
| − | + | find REGEX 'Y101|Y100|Y102' in l_lfart. | |
| − | + | if sy-subrc = 0. | |
| − | + | write:/ 'continue'. | |
| − | + | else. | |
| − | + | write:/ 'Exit'. | |
| − | + | endif.</nowiki> | |
| + | |||
| + | ===obtener extensión de archivo=== | ||
| + | <nowiki> | ||
| + | FORM get_extension USING iv_file TYPE string | ||
| + | CHANGING ev_ex TYPE string. | ||
| + | |||
| + | DATA: lt_match_result TYPE match_result_tab. | ||
| + | DATA: lv_regex TYPE string, | ||
| + | lv_string TYPE string. | ||
| + | DATA: lv_matches TYPE i. | ||
| + | DATA: lv_file(250). | ||
| + | |||
| + | lv_regex = '\.([^.]+)$'. | ||
| + | lv_string = iv_file. | ||
| + | |||
| + | lv_file = iv_file. | ||
| + | |||
| + | FIND ALL OCCURRENCES OF REGEX lv_regex IN lv_string | ||
| + | IN CHARACTER MODE RESPECTING CASE | ||
| + | MATCH COUNT lv_matches RESULTS lt_match_result. | ||
| + | IF lv_matches > 0. | ||
| + | |||
| + | DESCRIBE TABLE lt_match_result LINES DATA(lv_lines). | ||
| + | READ TABLE lt_match_result INTO DATA(ls_result) INDEX lv_lines. "get the last occurrence | ||
| + | |||
| + | ls_result-offset = ls_result-offset + 1. | ||
| + | |||
| + | ev_ex = lv_file+ls_result-offset. | ||
| + | ENDIF. | ||
| + | |||
| + | ENDFORM.</nowiki> | ||
| + | |||
| + | ===Encontrar primer espacio en blanco=== | ||
| + | En este ejemplo separamos el código de la transacción con su texto | ||
| + | VA01 Create Sales Order | ||
| + | ^(\S*)\s | ||
| + | |||
| + | ===Validar Hora=== | ||
| + | Para validar una hora en formato HH:MM (24 horas) donde los ceros a la izquierda sean obligatorios (ej. 09:05), utiliza la siguiente expresión regular: [1] | ||
| + | |||
| + | ^(0[0-9]|1[0-9]|2[0-3]):[0-5][0-9]$ | ||
| + | |||
| + | Explicación del patrón: | ||
| + | * ^ e $: Indican el inicio y el final de la cadena, asegurando que no haya caracteres adicionales. [1, 2] | ||
| + | * (0[0-9]|1[0-9]|2[0-3]): Valida la sección de la hora. | ||
| + | ** 0[0-9]: Permite horas desde 00 hasta 09. | ||
| + | ** 1[0-9]: Permite horas desde 10 hasta 19. | ||
| + | ** 2[0-3]: Permite horas desde 20 hasta 23. [1, 2] | ||
| + | * :: Separa las horas de los minutos. | ||
| + | * [0-5][0-9]: Valida los minutos del 00 al 59. [1] | ||
| + | |||
| + | opciones: | ||
| + | *Horas con cero inicial opcional (ej. 9:05): | ||
| + | ^([0-1]?[0-9]|2[0-3]):[0-5][0-9]$ | ||
| + | *Formato de 12 horas con AM/PM (ej. 09:05 PM): | ||
| + | ^(0?[1-9]|1[0-2]):[0-5][0-9] ?[AaPp][Mm]$ | ||
| + | *Máximo horas 99:59 | ||
| + | ^([0-9]{1,2}):([0-5][0-9])$ | ||
| + | ====Ejemplos en EXITS==== | ||
| + | <nowiki> | ||
| + | FUNCTION conversion_exit_zhora_input. | ||
| + | *"---------------------------------------------------------------------- | ||
| + | *"*"Interfase local | ||
| + | *" IMPORTING | ||
| + | *" VALUE(INPUT) | ||
| + | *" EXPORTING | ||
| + | *" VALUE(OUTPUT) | ||
| + | *"---------------------------------------------------------------------- | ||
| + | *01:30 => 1,5 hrs | ||
| + | |||
| + | DATA: lt_match_result TYPE match_result_tab. | ||
| + | DATA: lv_regex TYPE string, | ||
| + | lv_string TYPE string. | ||
| + | DATA: lv_matches TYPE i. | ||
| + | |||
| + | DATA: lv_hora_texto TYPE char5, | ||
| + | lv_horas TYPE i, | ||
| + | lv_minutos TYPE i, | ||
| + | lv_decimal TYPE p LENGTH 8 DECIMALS 2. | ||
| + | |||
| + | lv_string = input. | ||
| + | lv_regex = '^([0-1]?[0-9]|2[0-3]):[0-5][0-9]$'. | ||
| + | |||
| + | FIND ALL OCCURRENCES OF REGEX lv_regex IN lv_string | ||
| + | IN CHARACTER MODE RESPECTING CASE | ||
| + | MATCH COUNT lv_matches RESULTS lt_match_result. | ||
| + | IF lv_matches LE 0. | ||
| + | MESSAGE e000(0k) WITH 'Formato horas inválido, debe ser en HH:MM'. | ||
| + | ENDIF. | ||
| + | |||
| + | lv_hora_texto = input. | ||
| + | |||
| + | * 1. Separamos las horas y los minutos | ||
| + | SPLIT lv_hora_texto AT ':' INTO DATA(lv_hr_str) DATA(lv_min_str). | ||
| + | lv_horas = lv_hr_str. | ||
| + | lv_minutos = lv_min_str. | ||
| + | |||
| + | * 2. Aplicamos la fórmula matemática | ||
| + | lv_decimal = lv_horas + ( lv_minutos / 60 ). | ||
| + | |||
| + | output = lv_decimal. | ||
| + | |||
| + | ENDFUNCTION. | ||
| + | |||
| + | FUNCTION CONVERSION_EXIT_ZHORA_OUTPUT. | ||
| + | *"---------------------------------------------------------------------- | ||
| + | *"*"Interfase local | ||
| + | *" IMPORTING | ||
| + | *" VALUE(INPUT) | ||
| + | *" EXPORTING | ||
| + | *" VALUE(OUTPUT) | ||
| + | *"---------------------------------------------------------------------- | ||
| + | *1,5 horas => 01:30 | ||
| + | |||
| + | DATA: lv_decimal TYPE p DECIMALS 2 VALUE '8.75', " Ejemplo: 8.75 horas | ||
| + | lv_minutos_totales TYPE i, | ||
| + | lv_horas TYPE i, | ||
| + | lv_minutos TYPE i, | ||
| + | lv_resultado TYPE string. | ||
| + | |||
| + | lv_decimal = input. | ||
| + | |||
| + | " 1. Convertir horas decimales a minutos totales | ||
| + | lv_minutos_totales = lv_decimal * 60. | ||
| + | |||
| + | " 2. Calcular horas (división entera por 60) | ||
| + | lv_horas = lv_minutos_totales DIV 60. | ||
| + | |||
| + | " 3. Calcular minutos restantes | ||
| + | lv_minutos = lv_minutos_totales MOD 60. | ||
| + | |||
| + | " 4. Formatear el resultado a HH:MM con ceros a la izquierda | ||
| + | lv_resultado = |{ lv_horas WIDTH = 2 ALIGN = RIGHT PAD = '0' }:{ lv_minutos WIDTH = 2 ALIGN = RIGHT PAD = '0' }|. | ||
| + | |||
| + | CONDENSE lv_resultado. | ||
| + | |||
| + | output = lv_resultado. " Salida esperada: 08:45 | ||
| + | |||
| + | ENDFUNCTION. | ||
| + | </nowiki> | ||
==DEMOS== | ==DEMOS== | ||
RS_SIC_REGEX_CHECK | RS_SIC_REGEX_CHECK | ||
DEMO_REGEX_TOY | DEMO_REGEX_TOY | ||
| + | DEMO_REGEX (con PCRE (Perl Compatible Regular Expressions) ) | ||
==Regular Expression Patterns== | ==Regular Expression Patterns== | ||
| − | |||
| − | |||
| − | |||
| − | |||
| − | |||
| − | |||
| − | |||
| − | |||
| − | |||
| − | |||
| − | |||
| − | |||
| − | |||
| − | |||
| − | |||
| − | |||
| − | |||
| − | |||
| − | |||
| − | |||
| − | |||
| − | |||
| − | |||
| − | |||
| − | |||
| − | |||
| − | |||
| − | |||
| − | |||
| − | |||
| − | |||
| − | |||
| − | |||
| − | |||
| − | |||
| − | |||
| − | |||
| − | |||
| − | |||
| − | |||
| − | |||
| − | |||
| − | |||
| − | |||
| − | |||
| − | |||
| − | |||
| − | |||
| − | |||
| − | |||
| − | |||
| − | |||
| − | |||
| − | |||
| − | |||
| − | |||
| − | |||
| − | |||
| − | |||
| − | |||
| − | |||
| − | |||
| − | |||
| − | |||
| − | |||
| − | |||
| − | |||
| − | |||
| − | |||
| − | |||
| + | |||
| + | {| class="wikitable" | ||
| + | |+ Special Characters for single character string | ||
| + | |- | ||
| + | ! Special character !! Meaning | ||
| + | |- | ||
| + | | . || Placeholder for any single character | ||
| + | |- | ||
| + | | \C || Placeholder for any single character | ||
| + | |- | ||
| + | | \d || Placeholder for any single digit | ||
| + | |- | ||
| + | | \D || Placeholder for any character other than a digit | ||
| + | |- | ||
| + | | \l || Placeholder for any lower-case letter | ||
| + | |- | ||
| + | | \L || Placeholder for any character other than a lower-case letter | ||
| + | |- | ||
| + | | \s || Placeholder for a blank character | ||
| + | |- | ||
| + | | \S || Placeholder for any character other than a blank character | ||
| + | |- | ||
| + | | \u || Placeholder for any upper-case letter | ||
| + | |- | ||
| + | | \U || Placeholder for any character other than an upper-case letter | ||
| + | |- | ||
| + | | \w || Placeholder for any alphanumeric character including _ | ||
| + | |- | ||
| + | | \W || Placeholder for any non-alphanumeric character except for _ | ||
| + | |- | ||
| + | | [ ] || Definition of a value set for single characters | ||
| + | |- | ||
| + | | [^ ] || Negation of a value set for single characters | ||
| + | |- | ||
| + | | [ - ] || Definition of a range in a value set for single characters | ||
| + | |- | ||
| + | | [ [:alnum:] ] || Description of all alphanumeric characters in a value set | ||
| + | |- | ||
| + | | [ [:alpha:] ] || Description of all letters in a value set | ||
| + | |- | ||
| + | | [ [:blank:] ] || Description for blank characters and horizontal tabulators in a value set | ||
| + | |- | ||
| + | | [ [:cntrl:] ] || Description of all control characters in a value set | ||
| + | |- | ||
| + | | [ [:digit:] ] || Description of all digits in a value set | ||
| + | |- | ||
| + | | [ [:graph:] ] || Description of all graphic special characters in a value set | ||
| + | |- | ||
| + | | [ [:lower:] ] || Description of all lower-case letters in a value set | ||
| + | |- | ||
| + | | [ [:print:] ] || Description of all displayable characters in a value set | ||
| + | |- | ||
| + | | [ [:punct:] ] || Description of all punctuation characters in a value set | ||
| + | |- | ||
| + | | [ [:space:] ] || Description of all blank characters, tabulators, and carriage feeds in a value set | ||
| + | |- | ||
| + | | [ [:unicode:] ] || Description of all Unicode characters in a value set with a code larger than 255 | ||
| + | |- | ||
| + | | [ [:upper:] ] || Description of all upper-case letters in a value set | ||
| + | |- | ||
| + | | [ [:word:] ] || Description of all alphanumeric characters in a value set, including _ | ||
| + | |- | ||
| + | | [ [:xdigit:] ] || Description of all hexadecimal digits in a value set | ||
| + | |- | ||
| + | | \a \f \n \r \t \v || Diverse platform-specific control characters | ||
| + | |- | ||
| + | | [..] || Reserved for later enhancements | ||
| + | |- | ||
| + | | [==] || Reserved for later enhancements | ||
| + | |} | ||
| + | |||
| + | {| class="wikitable" | ||
| + | |+ Special Characters for character string patterns | ||
| + | |- | ||
| + | ! Special character !! Meaning | ||
| + | |- | ||
| + | | {n} || Concatenation of n single characters | ||
| + | |- | ||
| + | | {n,m} || Concatenation of at least n and a maximum of m single characters | ||
| + | |- | ||
| + | | {n,m}? || Reserved for later enhancements | ||
| + | |- | ||
| + | | ? || One or no single characters | ||
| + | |- | ||
| + | | * || Concatenation of any number of single characters including 'no characters' | ||
| + | |- | ||
| + | | *? || Reserved for later enhancements | ||
| + | |- | ||
| + | | + || Concatenation of any number of single characters excluding 'no characters' | ||
| + | |- | ||
| + | | +? || Reserved for later enhancements | ||
| + | |- | ||
| + | | <nowiki>|</nowiki> || Linking of two alternative expressions | ||
| + | |- | ||
| + | | ( ) || Definition of subgroups with registration | ||
| + | |- | ||
| + | | (?: ) || Definition of subgroups without registration | ||
| + | |- | ||
| + | | \1, \2, \3 ... || Placeholder for the register of subgroups | ||
| + | |- | ||
| + | | \Q ... \E || Definition of a string of literal characters | ||
| + | |- | ||
| + | | (? ... ) || Reserved for later enhancements | ||
| + | |} | ||
| + | |||
| + | |||
| + | {| class="wikitable" | ||
| + | |+ Special Characters for search string | ||
| + | |- | ||
| + | ! Special character !! Meaning | ||
| + | |- | ||
| + | | ^ || Anchor character for the start of a line | ||
| + | |- | ||
| + | | \A || Anchor character for the start of a character string | ||
| + | |- | ||
| + | | $ || Anchor character for the end of a line | ||
| + | |- | ||
| + | | \Z || Anchor character for the end of a character string | ||
| + | |- | ||
| + | | \< || Start of a word | ||
| + | |- | ||
| + | | \> || End of a word | ||
| + | |- | ||
| + | | \b || Start or end of a word | ||
| + | |- | ||
| + | | \B || Space between characters within a word | ||
| + | |- | ||
| + | | (?= ) || Preview condition | ||
| + | |- | ||
| + | | (?! ) || Negated preview condition | ||
| + | |} | ||
| + | |||
| + | |||
| + | {| class="wikitable" | ||
| + | |+ Special Characters for replacement texts | ||
| + | |- | ||
| + | ! Special character !! Meaning | ||
| + | |- | ||
| + | | $0, $& || Placeholder for the whole found location | ||
| + | |- | ||
| + | | $1, $2, $3... || Placeholder for the register of subgroups | ||
| + | |- | ||
| + | | $` || Placeholder for the text before the found location | ||
| + | |} | ||
| + | ===ejemplos=== | ||
| + | ^ start line | ||
| + | $ end line | ||
| + | ^\w+$ matches one or more word characters (same as [a-zA-Z0-9_]+). Ex. TRUE: 33737733aaaaaa_aaaaaa FALSE: 33737733aaa+aaa_aaaaaa | ||
| + | ^[0-9]+$ or ^\d+$ Full Numeric Strings | ||
| + | \S+, one or more non-whitespaces | ||
[[Category:ABAP]] | [[Category:ABAP]] | ||
Latest revision as of 21:59, 6 September 2026
Contents
- 1 PCRE (Perl Compatible Regular Expressions)
- 2 Ejemplos REGEX
- 2.1 Ejemplo de Uso de regex en ABAP
- 2.2 validar rut (muy simple)
- 2.3 valida e-mail
- 2.4 validar Números
- 2.5 Elimina prefijo
- 2.6 convertir fecha (yyyymmdd->dd/mm/yyyy)
- 2.7 convertir TIMESTAMP
- 2.8 Convierte folio
- 2.9 usar REGEX como IF
- 2.10 obtener extensión de archivo
- 2.11 Encontrar primer espacio en blanco
- 2.12 Validar Hora
- 3 DEMOS
- 4 Regular Expression Patterns
PCRE (Perl Compatible Regular Expressions)
In modern ABAP (SAP NetWeaver 7.55 and higher), using the REPLACE FIRST OCCURRENCE OF REGEX statement triggers a syntax warning because POSIX-style regular expressions are obsolete. The ABAP compiler flags standard inline regex strings in these older statements as deprecated.
Ejemplo 1
data: sub1 TYPE c LENGTH 80,
sub2 TYPE c LENGTH 80,
sub3 TYPE c LENGTH 80,
sub4 TYPE c LENGTH 80,
sub5 TYPE c LENGTH 80,
sub6 TYPE c LENGTH 80.
DATA lv_text TYPE string.
lv_text = sy-datlo.
" Create a PCRE-compliant regex object
DATA(lo_regex) = cl_abap_regex=>create_pcre( pattern = '(\d{4})(\d{2})(\d{2})' ).
REPLACE REGEX lo_regex IN lv_text WITH '$3/$2/$1'.
lv_text = sy-datlo.
FIND REGEX lo_regex IN lv_text SUBMATCHES sub1 sub2 sub3.
Ejemplo REPLACE_REGEXPR en CDS view
@AccessControl.authorizationCheck: #NOT_REQUIRED
define view entity demo_cds_sql_func_string_ve
as select from demo_expressions
{
length( char1 ) as r_length,
instr( char1, 'CD' ) as r_instr,
concat( char1, char2 ) as r_concat,
concat_with_space( char1, char2, 10 ) as r_concat_with_space,
left( char1, 3 ) as r_left,
lower( char1 ) as r_lower,
right( char2, 3 ) as r_right,
lpad( char1, 10, 'x' ) as r_lpad,
rpad( char2, 10, 'y' ) as r_rpad,
ltrim( char1, 'A' ) as r_ltrim,
rtrim( char1, 'E' ) as r_rtrim,
replace_regexpr( pcre => '\\Cg',
value => char2,
with => 'bb',
result_length => 4 ) as r_replace_regexpr,
replace( char2, 'ghi', 'XXX' ) as r_replace,
substring( char2, 2, 3 ) as r_substring,
upper( char2 ) as r_upper
}
Ejemplos REGEX
Ejemplo de Uso de regex en ABAP
DATA: lt_match_result TYPE match_result_tab.
data: l_regex type string,
l_string type string.
data: l_matches TYPE i.
l_regex = '^[^<>()\[\]\\,;:\s@"`]+@([a-zA-Z\-0-9]+\.)+[a-zA-Z]{2,}$'.
l_string = 'pablo.tapia@sapwiki.cl'.
FIND ALL OCCURRENCES OF REGEX l_regex IN l_string
IN CHARACTER MODE RESPECTING CASE
MATCH COUNT l_matches RESULTS lt_match_result.
if l_matches le 0.
message i000(0k) with 'E-mail no valido' display like 'E'.
return.
endif.
validar rut (muy simple)
FIND REGEX '[0-9]{1,8}-([0-9]|K)' IN l_strng.
valida e-mail
^[^<>()\[\]\\,;:\s@"`]+@([a-zA-Z\-0-9]+\.)+[a-zA-Z]{2,}$
validar Números
validar número
1.1111 correcto
-1.1111 correcto
1.11111- correcto
1111 correcto
^[-?0-9]+([.])?([0-9]+)?-?$
números de 2 enteros y 7 decimales
1.1234567 correcto
11.1234560 correcto
^[0-9]{1,2}\.([0-9]{7})+$
con signo izquierda
-1.1234567 correcto
1.1234567 correcto
^-?[0-9]{1,2}\.([0-9]{7})+$
con signo derecha o izquierda
^-?[0-9]{1,2}\.([0-9]{7})+-?$
validar número entero
^[0-9]+$
numero NNN.NN
valido
111.1
11.11
1
^\d{1,3}(\.\d{1,2})?$
numero entero con máximo de 13 caracteres
valido
1234567890111
111
1
^\d{1,13}$
MODULE verificar_folio INPUT.
DATA l_string TYPE string.
DATA l_folio(7) TYPE n.
IF zfi_datoscajas-folio IS NOT INITIAL.
MOVE zfi_datoscajas-folio TO l_string.
CONDENSE l_string.
FIND REGEX '[^\d]' IN l_string IN CHARACTER MODE RESPECTING CASE.
IF sy-subrc = 0.
MESSAGE e000(0k) WITH 'Folio deber contener solo números'.
ELSE.
MOVE l_string TO l_folio.
MOVE l_folio TO zfi_datoscajas-folio.
ENDIF.
ENDIF.
ENDMODULE.
Elimina prefijo
* NC00000009 -> 00000009 *saca prefijos de XBLNR data l_xblnr type string. l_xblnr = vbrk-xblnr. REPLACE all OCCURRENCES OF REGEX '[[:alpha:]]' IN l_xblnr with ''. if sy-subrc = 0. .... endif.
ejemplo 2
REPLACE all OCCURRENCES OF REGEX '[^\d]' in l_xblnr WITH ''.
convertir fecha (yyyymmdd->dd/mm/yyyy)
data l_fecha(10).
l_fecha = sy-datum.
replace FIRST OCCURRENCE OF REGEX '(\d{4})(\d{2})(\d{2})'
in l_fecha WITH '$3/$2/$1'.
write:/ l_fecha.
convertir TIMESTAMP
DD.MM.YYYY HORA => YYYY-MM-DD HORA Ejemplo: 03.10.2025 14:55:44 => 2025-10-03 14:55:44
FORM get_timestamp CHANGING ev_timestamp TYPE string.
DATA: lv_short_timestamp TYPE timestamp.
DATA lv_timestamp(30).
GET TIME STAMP FIELD lv_short_timestamp.
WRITE lv_short_timestamp TO lv_timestamp TIME ZONE sy-zonlo.
REPLACE FIRST OCCURRENCE OF REGEX '(\d{2})\.(\d{2})\.(\d{4})\s(.*)'
IN lv_timestamp WITH '$3-$2-$1 $4'.
MOVE lv_timestamp TO ev_timestamp.
ENDFORM.
Convierte folio
* Folio1: PRmmaaRppnnnnnn
* Folio2: 0208020 + aa + mm + nnnnnn
* Ejemplo: PR0720R007188233 se convierte en 02080202007188233
*----------------------------------------------------------------------*
* --> p1 text
* <-- p2 text
*----------------------------------------------------------------------*
FORM conv_folio USING p_xblnr TYPE bsis-xblnr
CHANGING p_folio TYPE ze_folio.
DATA l_string TYPE string.
CLEAR p_folio.
l_string = p_xblnr.
REPLACE FIRST OCCURRENCE OF REGEX '(.{2})(.{2})(.{2})(.{1})(.{1})(.{2})(.{6})'
IN l_string WITH '0208020$3$2$7'.
IF sy-subrc = 0.
p_folio = l_string.
ENDIF.
ENDFORM.
usar REGEX como IF
ejemplo para verificar por clase de entrega data l_lfart type string. l_lfart = likp-lfart. find REGEX 'Y101|Y100|Y102' in l_lfart. if sy-subrc = 0. write:/ 'continue'. else. write:/ 'Exit'. endif.
obtener extensión de archivo
FORM get_extension USING iv_file TYPE string
CHANGING ev_ex TYPE string.
DATA: lt_match_result TYPE match_result_tab.
DATA: lv_regex TYPE string,
lv_string TYPE string.
DATA: lv_matches TYPE i.
DATA: lv_file(250).
lv_regex = '\.([^.]+)$'.
lv_string = iv_file.
lv_file = iv_file.
FIND ALL OCCURRENCES OF REGEX lv_regex IN lv_string
IN CHARACTER MODE RESPECTING CASE
MATCH COUNT lv_matches RESULTS lt_match_result.
IF lv_matches > 0.
DESCRIBE TABLE lt_match_result LINES DATA(lv_lines).
READ TABLE lt_match_result INTO DATA(ls_result) INDEX lv_lines. "get the last occurrence
ls_result-offset = ls_result-offset + 1.
ev_ex = lv_file+ls_result-offset.
ENDIF.
ENDFORM.
Encontrar primer espacio en blanco
En este ejemplo separamos el código de la transacción con su texto
VA01 Create Sales Order ^(\S*)\s
Validar Hora
Para validar una hora en formato HH:MM (24 horas) donde los ceros a la izquierda sean obligatorios (ej. 09:05), utiliza la siguiente expresión regular: [1]
^(0[0-9]|1[0-9]|2[0-3]):[0-5][0-9]$
Explicación del patrón:
- ^ e $: Indican el inicio y el final de la cadena, asegurando que no haya caracteres adicionales. [1, 2]
- (0[0-9]|1[0-9]|2[0-3]): Valida la sección de la hora.
- 0[0-9]: Permite horas desde 00 hasta 09.
- 1[0-9]: Permite horas desde 10 hasta 19.
- 2[0-3]: Permite horas desde 20 hasta 23. [1, 2]
- :: Separa las horas de los minutos.
- [0-5][0-9]: Valida los minutos del 00 al 59. [1]
opciones:
- Horas con cero inicial opcional (ej. 9:05):
^([0-1]?[0-9]|2[0-3]):[0-5][0-9]$
- Formato de 12 horas con AM/PM (ej. 09:05 PM):
^(0?[1-9]|1[0-2]):[0-5][0-9] ?[AaPp][Mm]$
- Máximo horas 99:59
^([0-9]{1,2}):([0-5][0-9])$
Ejemplos en EXITS
FUNCTION conversion_exit_zhora_input.
*"----------------------------------------------------------------------
*"*"Interfase local
*" IMPORTING
*" VALUE(INPUT)
*" EXPORTING
*" VALUE(OUTPUT)
*"----------------------------------------------------------------------
*01:30 => 1,5 hrs
DATA: lt_match_result TYPE match_result_tab.
DATA: lv_regex TYPE string,
lv_string TYPE string.
DATA: lv_matches TYPE i.
DATA: lv_hora_texto TYPE char5,
lv_horas TYPE i,
lv_minutos TYPE i,
lv_decimal TYPE p LENGTH 8 DECIMALS 2.
lv_string = input.
lv_regex = '^([0-1]?[0-9]|2[0-3]):[0-5][0-9]$'.
FIND ALL OCCURRENCES OF REGEX lv_regex IN lv_string
IN CHARACTER MODE RESPECTING CASE
MATCH COUNT lv_matches RESULTS lt_match_result.
IF lv_matches LE 0.
MESSAGE e000(0k) WITH 'Formato horas inválido, debe ser en HH:MM'.
ENDIF.
lv_hora_texto = input.
* 1. Separamos las horas y los minutos
SPLIT lv_hora_texto AT ':' INTO DATA(lv_hr_str) DATA(lv_min_str).
lv_horas = lv_hr_str.
lv_minutos = lv_min_str.
* 2. Aplicamos la fórmula matemática
lv_decimal = lv_horas + ( lv_minutos / 60 ).
output = lv_decimal.
ENDFUNCTION.
FUNCTION CONVERSION_EXIT_ZHORA_OUTPUT.
*"----------------------------------------------------------------------
*"*"Interfase local
*" IMPORTING
*" VALUE(INPUT)
*" EXPORTING
*" VALUE(OUTPUT)
*"----------------------------------------------------------------------
*1,5 horas => 01:30
DATA: lv_decimal TYPE p DECIMALS 2 VALUE '8.75', " Ejemplo: 8.75 horas
lv_minutos_totales TYPE i,
lv_horas TYPE i,
lv_minutos TYPE i,
lv_resultado TYPE string.
lv_decimal = input.
" 1. Convertir horas decimales a minutos totales
lv_minutos_totales = lv_decimal * 60.
" 2. Calcular horas (división entera por 60)
lv_horas = lv_minutos_totales DIV 60.
" 3. Calcular minutos restantes
lv_minutos = lv_minutos_totales MOD 60.
" 4. Formatear el resultado a HH:MM con ceros a la izquierda
lv_resultado = |{ lv_horas WIDTH = 2 ALIGN = RIGHT PAD = '0' }:{ lv_minutos WIDTH = 2 ALIGN = RIGHT PAD = '0' }|.
CONDENSE lv_resultado.
output = lv_resultado. " Salida esperada: 08:45
ENDFUNCTION.
DEMOS
RS_SIC_REGEX_CHECK DEMO_REGEX_TOY DEMO_REGEX (con PCRE (Perl Compatible Regular Expressions) )
Regular Expression Patterns
| Special character | Meaning |
|---|---|
| . | Placeholder for any single character |
| \C | Placeholder for any single character |
| \d | Placeholder for any single digit |
| \D | Placeholder for any character other than a digit |
| \l | Placeholder for any lower-case letter |
| \L | Placeholder for any character other than a lower-case letter |
| \s | Placeholder for a blank character |
| \S | Placeholder for any character other than a blank character |
| \u | Placeholder for any upper-case letter |
| \U | Placeholder for any character other than an upper-case letter |
| \w | Placeholder for any alphanumeric character including _ |
| \W | Placeholder for any non-alphanumeric character except for _ |
| [ ] | Definition of a value set for single characters |
| [^ ] | Negation of a value set for single characters |
| [ - ] | Definition of a range in a value set for single characters |
| [ [:alnum:] ] | Description of all alphanumeric characters in a value set |
| [ [:alpha:] ] | Description of all letters in a value set |
| [ [:blank:] ] | Description for blank characters and horizontal tabulators in a value set |
| [ [:cntrl:] ] | Description of all control characters in a value set |
| [ [:digit:] ] | Description of all digits in a value set |
| [ [:graph:] ] | Description of all graphic special characters in a value set |
| [ [:lower:] ] | Description of all lower-case letters in a value set |
| [ [:print:] ] | Description of all displayable characters in a value set |
| [ [:punct:] ] | Description of all punctuation characters in a value set |
| [ [:space:] ] | Description of all blank characters, tabulators, and carriage feeds in a value set |
| [ [:unicode:] ] | Description of all Unicode characters in a value set with a code larger than 255 |
| [ [:upper:] ] | Description of all upper-case letters in a value set |
| [ [:word:] ] | Description of all alphanumeric characters in a value set, including _ |
| [ [:xdigit:] ] | Description of all hexadecimal digits in a value set |
| \a \f \n \r \t \v | Diverse platform-specific control characters |
| [..] | Reserved for later enhancements |
| [==] | Reserved for later enhancements |
| Special character | Meaning |
|---|---|
| {n} | Concatenation of n single characters |
| {n,m} | Concatenation of at least n and a maximum of m single characters |
| {n,m}? | Reserved for later enhancements |
| ? | One or no single characters |
| * | Concatenation of any number of single characters including 'no characters' |
| *? | Reserved for later enhancements |
| + | Concatenation of any number of single characters excluding 'no characters' |
| +? | Reserved for later enhancements |
| | | Linking of two alternative expressions |
| ( ) | Definition of subgroups with registration |
| (?: ) | Definition of subgroups without registration |
| \1, \2, \3 ... | Placeholder for the register of subgroups |
| \Q ... \E | Definition of a string of literal characters |
| (? ... ) | Reserved for later enhancements |
| Special character | Meaning |
|---|---|
| ^ | Anchor character for the start of a line |
| \A | Anchor character for the start of a character string |
| $ | Anchor character for the end of a line |
| \Z | Anchor character for the end of a character string |
| \< | Start of a word |
| \> | End of a word |
| \b | Start or end of a word |
| \B | Space between characters within a word |
| (?= ) | Preview condition |
| (?! ) | Negated preview condition |
| Special character | Meaning |
|---|---|
| $0, $& | Placeholder for the whole found location |
| $1, $2, $3... | Placeholder for the register of subgroups |
| $` | Placeholder for the text before the found location |
ejemplos
^ start line $ end line ^\w+$ matches one or more word characters (same as [a-zA-Z0-9_]+). Ex. TRUE: 33737733aaaaaa_aaaaaa FALSE: 33737733aaa+aaa_aaaaaa ^[0-9]+$ or ^\d+$ Full Numeric Strings \S+, one or more non-whitespaces