Dit zou moeten werken op voorwaarde dat je geen invoer hebt die eruitziet als %ABC#%ABC#
SELECT REGEXP_REPLACE( '%ABC#abc\%ABC#', '((^|[^\])(\\\\)*)%ABC#', '\1XXX' )
FROM DUAL;
Dit komt overeen met:
- Het begin van de tekenreeks
^
of een niet-slash-teken[^\]
gevolgd door een willekeurig aantal paren slash-tekens en ten slotte de tekens%ABC#
. Dit komt overeen met%ABC#
,\\%ABC#
,\\\\%ABC#
enzovoort, maar komt niet overeen met\%ABC#
,\\\%ABC#
,\\\\\%ABC#
waar een schuine streep staat die ontsnapt aan de%
karakter.
De vervanging omvat de eerste capture-groep, aangezien de expressie kan overeenkomen met een voorafgaand niet-slash-teken en paren slashes en deze moeten worden bewaard in de uitvoer.
Bijwerken
Dit wordt een beetje ingewikkeld, maar het zal herhaalde overeenkomsten opleveren:
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;
Het gebruikt een gecorreleerde subquery om de string te splitsen in substrings die eindigen op %ABC#
of het einde van de string (dit is het bit in de TABLE( CAST( MULTISET( ) .. ) )
) en voegt deze substrings vervolgens opnieuw samen nadat de vervanging aan het einde van elke substring is uitgevoerd.