Dette burde fungere, forudsat at du ikke har et input, der ligner %ABC#%ABC#
SELECT REGEXP_REPLACE( '%ABC#abc\%ABC#', '((^|[^\])(\\\\)*)%ABC#', '\1XXX' )
FROM DUAL;
Dette vil enten matche:
- Starten af strengen
^eller et ikke-skråstreg tegn[^\]efterfulgt af et vilkårligt antal par skråstreger og til sidst tegnene%ABC#. Dette vil matche%ABC#,\\%ABC#,\\\\%ABC#og så videre, men vil ikke matche\%ABC#,\\\%ABC#,\\\\\%ABC#hvor der er en skråstreg, der undslipper%tegn.
Erstatningen inkluderer den første indfangningsgruppe, da udtrykket kan matche et foregående tegn uden skråstreg og par af skråstreger, og disse skal bevares i outputtet.
Opdater
Dette bliver en smule kompliceret, men det vil gøre gentagne kampe:
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;
Den bruger en korreleret underforespørgsel til at opdele strengen i understrenge, der ender med %ABC# eller slutningen af strengen (dette er bit inde i TABLE( CAST( MULTISET( ) .. ) ) ) og sammenkæder derefter disse understrenge igen efter at have udført udskiftningen i slutningen af hver understreng.