如何在oracle中替换多个字符?

时间:2015-09-25 09:41:06

标签: sql oracle oracle11g

如何替换组合中的多个整个字符??

以下代码替换了多个字符,但它也会扰乱组合中的字符。

SELECT regexp_replace('a,ca,va,ea,r,y,q,b,g','(a|y|q|g)','X') RESULT FROM dual;

当前输出:

RESULT 
--------------------
X,cX,vX,eX,r,X,X,b,X

预期产出:

RESULT 
------------------------
'X,ca,va,ea,r,X,X,b,X 

我只想更换单独的整个字符(' a'' y',' q'' g'),但不是1个组合(' ca',' va',' ea')...

8 个答案:

答案 0 :(得分:1)

因为您使用逗号分隔,''您可以将其与',a,'

结合使用

这将只替换单个a。

答案 1 :(得分:1)

你可以试试以下:

with t as
    (
        select 'a,ca,va,ea,r,y,q,b,g' str
        from dual
    )
select substr(sys_connect_by_path(regexp_replace(regexp_substr(str, '[^,]+', 1, level), '^(a|y|q|g)$', 'X'), ','), 2) as str
from t
where connect_by_isleaf = 1
    connect by level <= length(regexp_replace(str, '[^,]*')) + 1;

答案 2 :(得分:0)

你会查找单词边界,即\ b,但不幸的是,Oracle的regexp_replace不支持。

因此,让我们寻找一个非单词字符\ W或开头^或结尾$。

select
  regexp_replace('a,ca,va,ea,r,y,q,b,g','(^|$|\W)(a|y|q|g)(^|$|\W)','\1X\3') as result
from dual;

为了不删除非单词字符,我们必须在替换字符串中使用它们:\ 1表示第一个表达式中的表达式,\ 3表示第三个字符表中的表达式。因此,我们只改变第二个括号中的表达式,即a,y,q或g,用X.

不幸的是上面给出了

X,ca,va,ea,r,X,q,b,X

q没有被替换,因为我们认识到',y',因此被定位为'g',而我们需要定位在',g',以便将g识别为单词。

所以我们需要在迭代中替换(即递归):

with results(txt, num) as
(
  select 'a,ca,va,ea,r,y,q,b,g' as txt, 0 as num from dual
  union all
  select regexp_replace(txt, '(^|$|\W)(a|y|q|g)(^|$|\W)','\1X\3'), num + 1 as num
  from results
  where txt <> regexp_replace(txt, '(^|$|\W)(a|y|q|g)(^|$|\W)','\1X\3')
)
select max(txt) keep (dense_rank last order by num) as result
from results;
编辑:Kevin Esche是对的;当然,只需要做两次。因此你也可以这样做:

select
  regexp_replace(txt, search_str, replace_str) as result 
from
(
  select 
    regexp_replace(txt, search_str, replace_str) as txt, search_str, replace_str 
  from 
  (
    select 
      'a,ca,va,ea,r,y,q,y,q,b,g' as txt,
      '(^|$|\W)(a|y|q|g)(^|$|\W)' as search_str,
      '\1X\3' as replace_str 
    from dual
  )
);

答案 3 :(得分:0)

可悲的是,oracle并不支持前瞻和后视。但这是我提出的解决方案。

SELECT regexp_replace
          (regexp_replace
              ('a,ca,va,ea,r,y,q,b,g',
               '^[ayqg](,)|(,)[ayqg](,)|(,)[ayqg]$',
               '\2\4X\1\3'),'(,)[ayqg](,)','\1X\2') 
RESULT FROM dual;

我不得不两次遗憾地使用正则表达式,因为它没有找到两个相似的值后跟着并替换它。 ..,a,y,..被替换为..,X,y,..。所以第二次调用用精确的值替换缺少的[ayqg]。在第一个内部正则表达式调用中,替换第一个和最后一个值。

也许这可以简化为一个表达式,但我不符合oracle的正则表达式。

作为解释,我正在对逗号进行分组,并通过反向引用逗号来基本上将,[ayqg],替换为,X,

答案 4 :(得分:0)

with replaced_values as (
SELECT case when length(val)=1 then regexp_replace(val,'(a|y|q|g)','X') else val end new_val, lvl 
from (
  SELECT regexp_substr('a,ca,va,ea,r,y,q,b,g','[^,]+', 1, LEVEL) val, level lvl FROM dual
connect by regexp_substr('a,ca,va,ea,r,y,q,b,g','[^,]+',1, LEVEL) is not null
 ) all_values
 )
select lISTAGG(new_val, ',') WITHIN GROUP (ORDER BY lvl) RESULT 
 from replaced_values

此语句将数据转换为行,并仅替换包含一个字符的行。 然后,数据在一行中不显示

答案 5 :(得分:0)

这个sql也适用于'a ,,, b,c'这样的空条目以及更复杂的正则表达式:

with t as
 (select ',a,,ca,va,ea,bbb,ba,r,y,q,b,g,,,' as str,
         ',' as delimiter,
         '(a|y|q|g|ea|[b]*)' as regexp_expr,
         'X' as replace_expr
    from dual)

 (select substr (sys_connect_by_path(regexp_replace(substr(str,
              decode(level - 1, 0, 0, instr(str, ',', 1, level - 1)) + 1,
          decode(instr(str, ',', 1, level),
                 0,
                 length(str),
                 instr(str, ',', 1, level) - 1) -
          decode(level - 1, 0, 0, instr(str, ',', 1, level - 1))),
                    '^' || regexp_expr || '$',
                    replace_expr), ','), 2)
    from t
     where connect_by_isleaf = 1
  connect by level <= length(regexp_replace(str, '[^'|| delimiter||']')) + 1)

结果

,X,,ca,va,X,X,ba,r,X,X,X,X,,,

答案 6 :(得分:-1)

不了解Oracle,但我认为这样的事情可行。假设分隔符始终是逗号。

 SELECT 
 regexp_replace(regexp_replace(regexp_replace(regexp_replace(regexp_replace('a,ca,va,ea,r,y,q,b,g','(,a,|,y,|,q,|,g,)',',X,') ,'(,a,|,y,|,q,|,g,)',',X,'), '(^a,|^y,|^q,|^g,)','X,'), '(,a$|,y$|,q$|,g$)',',X'), '(^a$|^y$|^q$|^g$)','X')
 RESULT FROM test;

前两部分用中间的逗号替换单个字符,第三部分在字符串的开头替换,第四部分用于字符串的结尾,第五部分用于when时则字符串只有一个字符。

使用高级Regexp可以简化此答案。

答案 7 :(得分:-1)

我如何替换单词?

RS和OS ===> D,LS和IS ====> 需要SECTION_ID输出 1-LS-1991 1-P-1991 1-IS-1991 1-P-1991 1-RS-1991 1- D- 1991 1-OS-1991 1-D-1991