2016-02-12 2 views
2

Я создаю небольшую функцию replaceParam для строк и хотел бы избежать замены, e. г.Как избежать regexp_replace в Oracle?

select regexp_replace('%ABC# %ABC#','%ABC#', 'XXX') 
from dual; 

приводит к

XXX XXX 

, но я хочу, чтобы иметь возможность избежать Replacment, е. г. предшествуя символу a перед строкой, которая в противном случае будет заменена.

select regexp_replace('%ABC# \%ABC#','<themagicregexp>', 'XXX') 
from dual; 

должно привести к

XXX \%ABC# 

Я попробовал список символов, не соответствующий, но это не работает.

select regexp_replace('%ABC#abc\%ABC#','<themagicregexp>', 'XXX') 
from dual; 

должно привести к

XXXabc\%ABC# 

Кроме того, потому что кто-то говорил об этом: я не могу пойти с границами слова, так как это должно работать также:

yoyo%ABC#yoyo 

У меня есть ощущение, это можно сделать в одном регулярном выражении, но я просто этого не вижу?

+0

Что произойдет, если ваш вклад выглядит как ''% ABC# \\% ABC# ''? – Tomalak

+0

Вы пытаетесь направить меня в конструктивный недостаток моей идеи или в чем смысл вашего вопроса? На данный момент результат XXX \\ XXX, так как я не убегаю ничем не работаю. – bl4ckb0l7

+2

Я пытаюсь выяснить, что вы ожидаете в этом случае. Поведение решения должно по-прежнему определяться для этого случая, поскольку «никогда не будет такого, как это», не является хорошим предположением. – Tomalak

ответ

3

Это должно работать при условии, что вы не имеете вход, который выглядит как %ABC#%ABC#

SELECT REGEXP_REPLACE('%ABC#abc\%ABC#', '((^|[^\])(\\\\)*)%ABC#', '\1XXX') 
FROM DUAL; 

Это будет либо матч:

  • Начало строки ^ или не слэша [^\] за которым следует любое количество пар косых символов, затем, наконец, символы %ABC#. Это будет соответствовать %ABC#, \\%ABC#, \\\\%ABC# и т. Д., Но не соответствует \%ABC#, \\\%ABC#, \\\\\%ABC#, где есть косая черта, сбрасывающая символ %.

Замена включает в себя первую группу захвата, поскольку выражение может соответствовать предыдущему символу без косой черты и парам косых черт, и их необходимо сохранить на выходе.


Update

Это становится немного сложным, но это будет делать повторен матчи:

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() ..))), а затем повторно объединяет эти подстроки после выполнения замены в конце каждой подстроки.

+0

Это работает, спасибо. Я все еще должен понять, почему, но это помогает! edit: Вы помогли мне впервые получить обратные ссылки ... – bl4ckb0l7

+1

@bitschnau Объяснение регулярного выражения добавлено. Часть '(\\\\) *' адресует комментарий от @Tomalak по вашему вопросу. – MT0

+0

Почему% ABC#% ABC# не заменен на XXXXXX, так как # является символом без обратной обратной связи для меня, как и X, если первое замещение заменено перед продолжением и ищет больше шаблонов? – bl4ckb0l7

2

Мне нравится более простой подход:

select replace(
     regexp_replace(
      replace('%ABC# \%ABC#','\%','~~') 
      ,'%ABC#', 'XXX') 
     ,'~~','\%') 
from dual; 

Заметим, однако, что регулярное выражение не требуется в данном конкретном случае - это работает точно так же:

select replace(
     replace(
      replace('%ABC# \%ABC#','\%','~~') 
      ,'%ABC#', 'XXX') 
     ,'~~','\%') 
from dual; 
+0

'% ABC# ~~% ABC#' переходит в 'XXX \% XXX', когда он должен быть' XXX ~~ XXX' и '\\% ABC#' переходит в '\\% ABC#', когда он должен идти на '\\ XXX'. – MT0

+0

@ MT0 это просто пример - вы бы использовали строку подстановки, которая никогда не будет отображаться в реальном тексте. Я просто использовал '~~' в качестве примера. Кроме того, q никогда не указывал ничего особенного в '\\\', но это также можно было бы легко заменить, используя при этом ту же технику. –

+0

В комментариях были уточнены '\\', '\\\\', '\\\\\\'. Можете ли вы привести пример того, как его можно «легко» заменить? – MT0

Смежные вопросы