如何在Oracle中转义regexp_replace?

时间:2016-02-12 13:37:46

标签: regex oracle

我正在为Strings创建一个小的replaceParam函数,并希望能够逃避替换,e。克。

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

导致

XXX XXX

但我希望能够逃脱替换,e。 G。通过在字符串前面加一个\,否则将被替换。

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

我觉得这可以在一个正则表达式中完成,但我只是看不到它?

2 个答案:

答案 0 :(得分:3)

如果您没有看起来像%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( ) .. ) )内的位)然后重新在每个子字符串的末尾执行替换后连接这些子字符串。

答案 1 :(得分:2)

我喜欢更简单的方法:

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

但请注意,在这种特殊情况下不需要正则表达式 - 这也适用:

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