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.