2017-04-20 78 views
0

我想用oracle中的函数regexp_replace替换字符串中的单个字符。字符串中的替换应该以定义的模式开始。在oracle中使用regexp_replace将定义的模式替换为字符

实施例:

在字符串 “Heyho || HeyheyHo” 我将取代图案后面所有的 “Y” 字 “||”与字符“我”。在模式之前出现的字符应该被忽略。

字符串:置换后

Heyho || HeyheyHo 

字符串:

Heyho || HeiheiHo 

当然很容易的吗?

+0

字符串中总是有一个'||'吗?或可能是多次? –

回答

1

这是使用regexp_replace的解决方案。第四个参数是开始的位置。经过一番思考,我决定不跳过'+2'。不要懒惰和浪费周期测试你知道不是目标角色的角色。

SQL> with tbl(str) as (
    select 'Heyho || HeyheyHo' from dual 
    ) 
    select str before, 
      regexp_replace(str, 'y', 'i', instr(str, '||')+2) after 
    from tbl; 

BEFORE   AFTER 
----------------- ----------------- 
Heyho || HeyheyHo Heyho || HeiheiHo 

SQL> 
+0

谢谢你加里。这个解决方案就是我基本想要的,我下次更好地学习语法。 – happymapper

+0

我很好奇你为什么不选择Aleksej经过验证的更快的方法? –

1

您不需要正则表达式;你可以使用INSTRSUBSTRREPLACE,让您的需求:

with test(s) as (
     select 'Heyho || HeyheyHo' from dual 
    ) 
    /* the query */ 
    select s as input, 
      substr(s, 1, instr(s, '||')+1) || 
      replace(substr(s, instr(s, '||')+2), 'y', 'i') as result 
    from test 

给出:

INPUT    RESULT 
----------------- -------------------- 
Heyho || HeyheyHo Heyho || HeiheiHo 

工作原理:

select s as input, 
     substr(s, 1, instr(s, '||')+1) beforeDelimiter, 
     substr(s, instr(s, '||')+2) afterDelimiter, 
     replace(substr(s, instr(s, '||')+2), 'y', 'i') afterDelimiterEdited, 
     substr(s, 1, instr(s, '||')+1) || 
     replace(substr(s, instr(s, '||')+2), 'y', 'i') as result 
from test 

给出:

INPUT    BEFOREDELI AFTERDELIM AFTERDELIM RESULT 
----------------- ---------- ---------- ---------- -------------------- 
Heyho || HeyheyHo Heyho || HeyheyHo HeiheiHo Heyho || HeiheiHo 

如果字符串中出现多个||,则replace将在第一次发生后修改字符。

根据Mathguy的评论,我不能说这个解决方案比正则表达式更快。

与正则表达式中的溶液可以是:

select regexp_replace(s, 'y', 'i', instr(s, '||')) as result 

这里是2代表小的性能测试创建的相同方式用相同的数据(5个百万行):

SQL> create table testA3(s) as 
    2 select regexp_replace(s, 'y', 'i', instr(s, '||')) as result 
    3 from testA; 

Table created. 

Elapsed: 00:00:30.75 
SQL> create table testB3(s) as 
    2 select substr(s, 1, instr(s, '||')+1) || 
    3    replace(substr(s, instr(s, '||')+2), 'y', 'i') as result 
    4 from testB; 

Table created. 

Elapsed: 00:00:14.82 

标准这里的做法似乎更快;使用3M行的相同测试需要18秒的正则表达式方法和7秒的标准方法。

该测试当然不是详尽无遗,结果可能会根据许多事情而改变,但它是一个点,要考虑标准方式是一种很好的正则表达式替代,即使在这种情况下,需要许多标准操作来获得正则表达式的结果相同。

这是3M行的完整测试;我做了一个CREATE和2 INSERT s,以避免内存问题与CONNECT BY非常高的水平。

此外,在3M和5M行测试之间,我删除了表并重新创建它们,以确保缓存不会影响结果。

SQL> create table testA(s) as 
    2 select 'Heyho || HeyheyHo' || level || 'HeyheyHo' 
    3 from dual 
    4 connect by level <= 1000000; 

Table created. 

SQL> create table testB(s) as 
    2 select 'Heyho || HeyheyHo' || level || 'HeyheyHo' 
    3 from dual 
    4 connect by level <= 1000000; 

Table created. 

SQL> insert into testB(s) 
    2 select 'Heyho || HeyheyHo' || to_char(level + 1000000) || 'HeyheyHo' 
    3 from dual 
    4 connect by level <= 1000000; 

1000000 rows created. 

SQL> insert into testA(s) 
    2 select 'Heyho || HeyheyHo' || to_char(level + 1000000) || 'HeyheyHo' 
    3 from dual 
    4 connect by level <= 1000000; 

1000000 rows created. 

SQL> insert into testB(s) 
    2 select 'Heyho || HeyheyHo' || to_char(level + 2000000) || 'HeyheyHo' 
    3 from dual 
    4 connect by level <= 1000000; 

1000000 rows created. 

SQL> insert into testA(s) 
    2 select 'Heyho || HeyheyHo' || to_char(level + 2000000) || 'HeyheyHo' 
    3 from dual 
    4 connect by level <= 1000000; 

1000000 rows created. 

SQL> select count(1), count(distinct s) from testA; 

    COUNT(1) COUNT(DISTINCTS) 
---------- ---------------- 
    3000000   3000000 

SQL> select count(1), count(distinct s) from testB; 

    COUNT(1) COUNT(DISTINCTS) 
---------- ---------------- 
    3000000   3000000 

SQL> set timing on 
SQL> create table testA2(s) as 
    2 select regexp_replace(s, 'y', 'i', instr(s, '||')+2) as result 
    3 from testA; 

Table created. 

Elapsed: 00:00:17.66 
SQL> create table testB2(s) as 
    2 select substr(s, 1, instr(s, '||')+1) || 
    3    replace(substr(s, instr(s, '||')+2), 'y', 'i') as result 
    4 from testB; 

Table created. 

Elapsed: 00:00:06.96 
SQL> 
+0

非常感谢您的快速和成功的答复,Aleksej – happymapper

+1

在大多数情况下,使用标准(非reg-exp)函数可以加快执行速度。然而,在这个例子中,我计算了每行六个字符串函数:两个'instr',两个'substr','replace'和一个串联。在这种情况下,使用正则表达式的解决方案可能会更快 - 使用一个“instr”和一个“regexp_replace”。标准功能更快,但速度不会快五倍。 – mathguy

+1

@mathguy我诚实地低估了这么多标准函数可能导致较慢解决方案的事实。我只是做了(并发布)一个小测试,以检查它是如何进行的,似乎标准方法仍然比正则表达式快。这只是一个单一的测试,但... – Aleksej