Difference between revisions of "SAP ABAP REGEX"

From SapWiki
Line 2: Line 2:
 
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.
 
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.
  
−
<nowiki>
+
===Ejemplo 1===
 +
<nowiki>
 
data: sub1    TYPE c LENGTH 80,
 
data: sub1    TYPE c LENGTH 80,
 
       sub2    TYPE c LENGTH 80,
 
       sub2    TYPE c LENGTH 80,
Line 23: Line 24:
  
 
</nowiki>
 
</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==
  

Revision as of 21:58, 6 September 2026

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 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
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
| 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 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


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