Това трябва да работи, при условие че нямате вход, който изглежда като %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( ) .. ) ) ) и след това повторно свързва тези поднизове след извършване на замяната в края на всеки подниз.