Điều này sẽ hoạt động miễn là bạn không có đầu vào giống như %ABC#%ABC#
SELECT REGEXP_REPLACE( '%ABC#abc\%ABC#', '((^|[^\])(\\\\)*)%ABC#', '\1XXX' )
FROM DUAL;
Điều này sẽ phù hợp với:
- Phần đầu của chuỗi
^
hoặc ký tự không dấu gạch chéo[^\]
theo sau là bất kỳ số cặp ký tự gạch chéo nào, sau đó là các ký tự%ABC#
. Điều này sẽ khớp với%ABC#
,\\%ABC#
,\\\\%ABC#
v.v ... nhưng sẽ không khớp với\%ABC#
,\\\%ABC#
,\\\\\%ABC#
nơi có một dấu gạch chéo thoát khỏi%
nhân vật.
Việc thay thế bao gồm nhóm bắt đầu tiên vì biểu thức có thể khớp với một ký tự không có dấu gạch chéo đứng trước và các cặp dấu gạch chéo và chúng cần được giữ nguyên trong đầu ra.
Cập nhật
Điều này hơi phức tạp nhưng nó sẽ thực hiện các kết quả trùng khớp lặp lại:
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;
Nó sử dụng một truy vấn phụ có tương quan để chia chuỗi thành các chuỗi con kết thúc bằng %ABC#
hoặc phần cuối của chuỗi (đây là bit bên trong TABLE( CAST( MULTISET( ) .. ) )
) và sau đó nối lại các chuỗi con này sau khi thực hiện thay thế ở cuối mỗi chuỗi con.