sql >> Base de Datos >  >> RDS >> Oracle

¿Cómo escapar de un regexp_replace en Oracle?

Esto debería funcionar siempre que no tenga una entrada que se parezca a %ABC#%ABC#

SELECT REGEXP_REPLACE( '%ABC#abc\%ABC#', '((^|[^\])(\\\\)*)%ABC#', '\1XXX' )
FROM DUAL;

Esto coincidirá con:

  • El comienzo de la cadena ^ o un carácter sin barra [^\] seguido de cualquier número de pares de caracteres de barra y, finalmente, los caracteres %ABC# . Esto coincidirá con %ABC# , \\%ABC# , \\\\%ABC# y así sucesivamente, pero no coincidirá con \%ABC# , \\\%ABC# , \\\\\%ABC# donde hay una barra que escapa del % personaje.

El reemplazo incluye el primer grupo de captura, ya que la expresión puede coincidir con un carácter anterior que no sea una barra oblicua y pares de barras, y estos deben conservarse en la salida.

Actualizar

Esto se vuelve un poco complicado pero hará coincidencias repetidas:

WITH Data ( VALUE ) AS (
  SELECT '%ABC#%ABC#' FROM DUAL
)
SELECT ( SELECT LISTAGG(
                  REGEXP_REPLACE( COLUMN_VALUE, '((^|[^\])(\\\\)*)%ABC#$', '\1XXX' ),
                  NULL
                ) WITHIN GROUP ( ORDER BY NULL )
         FROM   TABLE(
                  CAST(
                    MULTISET(
                      SELECT  REGEXP_SUBSTR( d.value, '.*?(%ABC#|$)', 1, LEVEL )
                      FROM    DUAL
                      CONNECT BY LEVEL < REGEXP_COUNT( d.value, '.*?(%ABC#|$)' )
                    AS SYS.ODCIVARCHAR2LIST
                  )
                )
       ) AS Value
FROM   Data d;

Utiliza una subconsulta correlacionada para dividir la cadena en subcadenas que terminan con %ABC# o el final de la cadena (este es el bit dentro de TABLE( CAST( MULTISET( ) .. ) ) ) y luego vuelve a concatenar estas subcadenas después de realizar el reemplazo al final de cada subcadena.