【问题标题】:Oracle - regexp_replace with nulls in a comma separated StringsOracle - regexp_replace 用逗号分隔的字符串中的空值
【发布时间】:2020-09-30 03:41:18
【问题描述】:

我有一个场景,我必须根据位置替换逗号分隔字符串中的值。 以下是案例:

案例一:

select regexp_replace('1,2,3','[^,]+',5,1,3)
from dual;

返回正确结果:1,2,5

案例 2:

select regexp_replace('1,,3','[^,]+',5,1,3)
from dual;

返回结果:1,,3

预期结果:1,,5

@Gary_W has written about the problem 使用该正则表达式模式来拆分字符串,正是因为它如何处理空标签

所以我尝试了案例 3​​:

select regexp_replace('1,,3','(.*?)(,|$)',5,1,3)
from dual;

返回预期结果:1,,5

但如果我尝试这个案例 4:

select regexp_replace('1,2,3','(.*?)(,|$)',5,1,2)
    from dual;

返回结果:1,53

预期结果:1,5,3

我知道我在使用正则表达式时做错了。有没有办法让 regexp_replace 在上述所有场景中都有效吗?

【问题讨论】:

  • 怎么样:不要将数字列表存储为分隔字符串? SQL 有一种存储列表的好方法;它被称为表格,而不是字符串。
  • 您的案例 4 没有按预期工作,因为模式匹配“消耗”了逗号,但没有与替换字符串一起放回。本着您提到的我的帖子的精神,亚历克斯的帖子将尾随字符(捕获的第 2 组)放回去。

标签: sql regex oracle regexp-replace


【解决方案1】:

我认为这可以满足您的要求:

regexp_replace(col, '[^,]*(,|$)','5\1', 1, 3)

这个想法是捕获0到N个逗号以外的连续字符,后跟一个逗号或字符串的结尾(后者被捕获)。然后将其替换为目标值,然后是捕获的部分。

【讨论】:

    【解决方案2】:

    如果你想坚持@Gary_W 的模式,那么你可以做一个(非常!)与@GMB 的提议类似的事情,但保留第二个捕获组:

     regexp_replace(str, '(.*?)(,|$)', '5\2', 1, 3)
    

    一些样本数据:

    with t (str) as (
                select '1,2,3' from dual
      union all select '1,,3' from dual
      union all select '1,2,3,4' from dual
      union all select '1,,3,4' from dual
      union all select '1,,,4,' from dual
      union all select ',,3' from dual
      union all select ',,3,' from dual
      union all select ',,,' from dual
      union all select '1' from dual
    )
    select str,
      regexp_replace(str, '(.*?)(,|$)', '5\2', 1, 3) as result
    from t;
    
    STR     RESULT    
    ------- ----------
    1,2,3   1,2,5     
    1,,3    1,,5      
    1,2,3,4 1,2,5,4   
    1,,3,4  1,,5,4    
    1,,,4,  1,,5,4,   
    ,,3     ,,5       
    ,,3,    ,,5,      
    ,,,     ,,5,      
    1       1         
    

    顺便说一句,@GMB 的方法在所有这些方面都得到了完全相同的结果。

    如果您想保留空的第三个元素,那么您可以使用 regexp_substr 版本选择性地应用替换:

    with t as (...)
    select str,
      case when regexp_substr(str, '(.*?)(,|$)', 1, 3, null, 1) is not null
        then regexp_replace(str, '(.*?)(,|$)', '5\2', 1, 3)
        else str
      end as result
    from t;
    
    STR     RESULT    
    ------- ----------
    1,2,3   1,2,5     
    1,,3    1,,5      
    1,2,3,4 1,2,5,4   
    1,,3,4  1,,5,4    
    1,,,4,  1,,,4,    
    ,,3     ,,5       
    ,,3,    ,,5,      
    ,,,     ,,,       
    1       1        
    

    【讨论】:

      猜你喜欢
      • 2016-05-28
      • 2023-01-03
      • 2020-08-30
      • 1970-01-01
      • 1970-01-01
      • 2013-08-19
      • 2016-05-21
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多