Regexp_substr表达式

时间:2016-05-10 14:58:39

标签: sql oracle

我的REGEXP表达式有问题,我想循环,每次迭代都会删除斜杠后的文本。我的表情现在看起来像这样

REGEXP_SUBSTR('L1161148/1/10', '.*(/)')

我得到L1161148 / 1 /而不是L1161148 / 1

3 个答案:

答案 0 :(得分:1)

您可以尝试在最后一个斜杠后删除字符串:

echo "compile" > lf.txt
cp lf.txt crlf.txt
unix2dos crlf.txt

答案 1 :(得分:1)

你正试图走到最后一个/然后"回顾"并保留之前的内容。使用正则表达式,您可以使用子表达式执行此操作,如下所示:

select regexp_substr('L1161148/1/10', '(.*)/.*', 1, 1, null, 1) from dual;

在这里,像往常一样,第一个参数" 1"意味着从哪里开始搜索,第二个" 1"意味着选择匹配的子字符串," null"意味着没有特殊的匹配修饰符(如不区分大小写的匹配等 - 这里不需要),以及最后的" 1"表示返回第一个子表达式 - "匹配模式中括号中的第一个内容。"

但是,只有在不能使用标准substr和instr(和translate)函数的情况下才能使用正则表达式。这里的工作很简单:

instr(text_string, '/', -1)

将为您提供LAST / in text_string的位置(-1表示查找最后一次出现,而不是第一次出现:从字符串末尾开始计数)。所以整个事情可以写成:

select substr('L1161148/1/10', 1, instr('L1161148/1/10', '/', -1) - 1) from dual;

编辑:根据Gary_W的解决方案,这里是对几个字符串的概括,并从每个输入字符串中删除连续的图层;仍然没有使用正则表达式(导致性能略快)并使用自Oracle版本11以来可用的递归CTE;我相信Gary的解决方案仅适用于Oracle 12c。

查询:(我改变了Gary的第二个输入字符串,以确保查询正常工作)

with tbl(item_id, input_str) as (
        select 1, 'L1161148/1/10/2/34/5/6'           from dual union all
        select 2, 'ALKD/FJV11/61148/123/456/789/1/2/3' from dual
     ),
     r (item_id, proc_string, stage) as (
        select item_id, input_str, 0 from tbl
        union all
        select item_id, substr(proc_string, 1, instr(proc_string, '/', -1) - 1), stage + 1
        from r
        where instr(proc_string, '/') > 0
     )
select * from r
order by item_id, stage;

输出:

   ITEM_ID PROC_STRING                                   STAGE
---------- ---------------------------------------- ----------
         1 L1161148/1/10/2/34/5/6                            0
         1 L1161148/1/10/2/34/5                              1
         1 L1161148/1/10/2/34                                2
         1 L1161148/1/10/2                                   3
         1 L1161148/1/10                                     4
         1 L1161148/1                                        5
         1 L1161148                                          6
         2 ALKD/FJV11/61148/123/456/789/1/2/3                0
         2 ALKD/FJV11/61148/123/456/789/1/2                  1
         2 ALKD/FJV11/61148/123/456/789/1                    2
         2 ALKD/FJV11/61148/123/456/789                      3
         2 ALKD/FJV11/61148/123/456                          4
         2 ALKD/FJV11/61148/123                              5
         2 ALKD/FJV11/61148                                  6
         2 ALKD/FJV11                                        7
         2 ALKD                                              8

答案 2 :(得分:1)

你说你想循环。

CAVEAT:这两个解决方案都假设没有NULL列表元素(所有斜杠之间都有值)。

SQL> with tbl(data) as (
     select 'L1161148/1/10' from dual
   )
   select level, nvl(substr(data, 1, instr(data, '/', 1, level)-1), data)  formatted
   from tbl
   connect by level <= regexp_count(data, '/') + 1  -- Loop # of delimiters +1 times
   order by level desc;

     LEVEL FORMATTED
---------- -------------
         3 L1161148/1/10
         2 L1161148/1
         1 L1161148

SQL>

编辑:处理多行:

SQL> with tbl(rownbr, col1) as (
        select 1, 'L1161148/1/10/2/34/5/6'           from dual
        union
        select 2, 'ALKDFJV1161148/123/456/789/1/2/3' from dual
   )
   SELECT rownbr, column_value substring_nbr,
          nvl(substr(col1, 1, instr(col1, '/', 1, column_value)-1), col1) formatted
        FROM tbl,
             TABLE(
               CAST(
                 MULTISET(SELECT LEVEL
                             FROM dual
                             CONNECT BY LEVEL <= REGEXP_COUNT(col1, '/')+1
                         ) AS sys.OdciNumberList
               )
             )
   order by rownbr, substring_nbr desc
   ;

    ROWNBR SUBSTRING_NBR FORMATTED
---------- ------------- --------------------------------
         1             7 L1161148/1/10/2/34/5/6
         1             6 L1161148/1/10/2/34/5
         1             5 L1161148/1/10/2/34
         1             4 L1161148/1/10/2
         1             3 L1161148/1/10
         1             2 L1161148/1
         1             1 L1161148
         2             7 ALKDFJV1161148/123/456/789/1/2/3
         2             6 ALKDFJV1161148/123/456/789/1/2
         2             5 ALKDFJV1161148/123/456/789/1
         2             4 ALKDFJV1161148/123/456/789
         2             3 ALKDFJV1161148/123/456
         2             2 ALKDFJV1161148/123
         2             1 ALKDFJV1161148

14 rows selected.

SQL>