Това трябва да работи, при условие че нямате вход, който изглежда като %ABC#%ABC#
SELECT REGEXP_REPLACE( '%ABC#abc\%ABC#', '((^|[^\])(\\\\)*)%ABC#', '\1XXX' )
FROM DUAL;
Това ще съответства или на:
- Началото на низа
^
или знак без наклонена черта[^\]
последвано от произволен брой двойки знаци за наклонена черта, след това накрая знаците%ABC#
. Това ще съответства на%ABC#
,\\%ABC#
,\\\\%ABC#
и т.н., но няма да съответства на\%ABC#
,\\\%ABC#
,\\\\\%ABC#
където има наклонена черта, която избягва%
характер.
Замяната включва първата група за улавяне, тъй като изразът може да съответства на предходен знак без наклонена черта и двойки наклонени черти и те трябва да бъдат запазени в изхода.
Актуализация
Това става малко сложно, но ще прави повтарящи се съвпадения:
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;
Той използва корелирана подзаявка, за да раздели низа на поднизове, които завършват с %ABC#
или края на низа (това е битът в TABLE( CAST( MULTISET( ) .. ) )
) и след това повторно свързва тези поднизове след извършване на замяната в края на всеки подниз.