使用Regex(Oracle)从Pipe-delimited String中获取值

时间:2015-11-18 17:21:30

标签: sql regex oracle regexp-replace regexp-substr

我有一个示例源代码字符串,如下所示,它采用管道分隔格式,因为值 obr 可以在任何地方。我需要从第一次出现的 obr 中获取管道的第二个值。因此对于下面的源字符串,预期的是,

源字符串:

select 'asd|dfg|obr|1|value1|end' text from dual
union all
select 'a|brx|123|obr|2|value2|end' from dual
union all
select 'hfv|obr|3|value3|345|pre|end' from dual

预期产出:

value1
value2
value3

我在oracle sql中尝试过以下regexp,但它运行不正常。

with t as (
            select 'asd|dfg|obr|1|value1|end' text from dual
            union all
            select 'a|brx|123|obr|2|value2|end' from dual
            union all
            select 'hfv|obr|3|value3|345|pre|end' from dual
            )
            select text,to_char(regexp_replace(text,'*obr\|([^|]*\|)([^|]*).*$', '\2')) output from t;

当字符串以OBR开头时它工作正常,但是当OBR像上面的样本一样处于中间时它不能正常工作。

任何帮助都将不胜感激。

2 个答案:

答案 0 :(得分:3)

不确定Oracle如何处理正则表达式,但从星号开始通常意味着您要查找零个或多个空字符。

您是否尝试过'^.*obr\|([^|]*\|)([^|]*).*$'

答案 1 :(得分:0)

这会处理null元素并包含在NVL()调用中,如果找不到'obr'或者在记录末尾发生太远而提供值,那么值2就不可能了:

SQL> with t(id, text) as (
     select 1, 'asd|dfg|obr|1|value1|end'      from dual
     union
     select 2, 'a|brx|123|obr|2|value2|end'    from dual
     union
     select 3, 'hfv|obr|3|value3|345|pre|end'  from dual
     union
     select 4, 'hfv|obr||value4|345|pre|end'   from dual
     union
     select 5, 'a|brx|123|obriem|2|value5|end' from dual
     union
     select 6, 'a|brx|123|obriem|2|value6|obr' from dual
   )
   select
     id,
     nvl(regexp_substr(text, '\|obr\|[^|]*\|([^|]*)(\||$)', 1, 1, null, 1), 'value not found') value
   from t;

        ID VALUE
---------- -----------------------------
         1 value1
         2 value2
         3 value3
         4 value4
         5 value not found
         6 value not found

6 rows selected.

SQL>

正则表达式基本上可以理解为“查找管道模式,然后是'obr',后跟管道,后跟零个或多个不是管道的字符,后跟管道,后跟零或更多不是管道的字符(在捕获的组中记住),后跟管道或行的末尾“。然后regexp_substr()调用返回第一个捕获的组,它是来自'obr'的管道2字段之间的字符集。