2017-10-18 99 views
2

我想知道是否有可能用另一个字符串加位置替换特定字符串而不使用PL/SQL块(循环,用户定义函数/存储过程,带函数构造...)。替换字符串与另一个字符串加上各自的位置

这里:st - >pos_num

输入:

"aa bbb st cccc dddd st eeeeeeeeeee ffff g st g h i st j k l m st" 

输出:

"aa bbb pos_1 cccc dddd pos_2 eeeeeeeeeee ffff g pos_3 g h i pos_4 j k l m pos_5" 

DBFiddle

我觉得这是有可能实现它的Wi第一行操作(也许是正则表达式)。

+1

是。可能与'REGEXP_INSTR','REGEXP_REPLACE'和'LEVEL'组合。 –

+0

是一个递归的cte好吗?或者你更喜欢只有一个班轮:)? –

+0

@VamsiPrabhala随时发布您的解决方案:)一行优雅的解决方案是首选,但不是必要的:) – lad2025

回答

0

使用MODEL条款:

select m_1 
from dual 
model dimension by (0 as key) 
measures (cast('st post aa bbb st cccc dddd st ee ffff g st g h i st j k l m st' 
       as varchar2(500)) as m_1) 
rules iterate (100) until(not regexp_like(m_1[0], '(|^)(st)(|$)')) 
(m_1[0] = regexp_replace(m_1[0], 
      '(|^)st(|$)','\1pos_'||to_char(ITERATION_NUMBER+1)||'\2',1,1)); 

DBFiddle Demo

输出:

pos_1 post aa bbb pos_2 cccc dddd pos_3 ee ffff g pos_4 g h i pos_5 j k l m pos_6 
+0

如果你对表演感兴趣,你可能仍然想尝试这两种方式。“模式”条款非常慢,但(1)也许你没有很多数据,所以你不在乎; (2)在任何情况下,唯一可以确定的方法是通过测试**你的**数据,而不是其他人的数据。 – mathguy

2

递归cte方法。

with cte(string,col,cnt,repl) as 
(select string,1,regexp_count(string,'st'),regexp_replace(string,'st','pos_'||to_char(1),1,1) as repl 
from test 
union all 
select string,col+1,cnt,regexp_replace(repl,'st','pos_'||to_char(col+1),1,1) as repl 
from cte 
--join it to the original table if there are multiple rows, on string column. 
where col<cnt 
) 
cycle col set cycle to 1 default 0 
select string,repl 
from cte 
where cnt=col 
+0

+1这个解决方案基本上是正确的。递归CTE导致循环违例,可以通过向递归CTE添加CYCLE子句来解决该问题。另外,不需要使用“计数”来切断递归;我在答案中展示了一种方法。但总体而言,解决方案很好。我将编辑答案以添加CYCLE子句。 – mathguy

1

这是一个稍微不同的使用递归CTE的解决方案。仅当它被空格(或字符串的开头或结尾)包围时,它才会查找st

with 
    inputs (str) as (
    select 'aa bbb st sccc dddd st eee fff g st g h i st j k l m st' from dual 
    union all 
    select 'st abc st st st where st is not st'      from dual 
    union all 
    select 'post st stop postal'          from dual 
), 
    r (lvl, str, new_str) as (
    select 1, str, str 
     from inputs 
    union all 
    select lvl + 1, str, 
      regexp_replace(new_str, '(|^)st(|$)', '\1pos_' || lvl || '\2', 1, 1) 
     from r 
     where regexp_like(new_str, '(|^)(st)(|$)') 
) 
select str, new_str 
from r 
where not regexp_like(new_str, '(|^)(st)(|$)') 
; 

STR              NEW_STR 
------------------------------------------------------- ---------------------------------------------------------------------- 
post st stop postal          post pos_1 stop postal 
aa bbb st sccc dddd st eee fff g st g h i st j k l m st aa bbb pos_1 sccc dddd pos_2 eee fff g pos_3 g h i pos_4 j k l m pos_5 
st abc st st st where st is not st      pos_1 abc pos_2 pos_3 pos_4 where pos_5 is not pos_6 
+0

感谢您的输入。将它与'MODEL'结合起来效果非常好:) – lad2025

相关问题