返回Oracle中正则表达式的所有匹配项

时间:2013-01-08 19:51:48

标签: sql regex oracle oracle11g oracle11gr2

我有一个包含名为COMMANDS的VARCHAR2列的表。

此列中的数据是一堆难以阅读的ZPL代码,它们将被发送到标签打印机,而在ZPL中,有几个标记形式为{TABLE.COLUMN}。

我想在COMMANDS中找到所有不同的{TABLE.COLUMN}标记的好列表。我编写了以下正则表达式来匹配令牌格式:

SELECT REGEXP_SUBSTR(COMMANDS,'\{\w+\.\w+\}') FROM MYTABLE;

正则表达式有效,但它只返回每行第一个匹配的标记。有没有办法返回每一行的所有正则表达式匹配?

我正在使用Oracle 11GR2。

编辑 - 以下是来自单行的一小部分数据样本 - 每行中有许多这样的行:

^FO360,065^AEN,25,10^FD{CUSTOMERS.CUST_NAME}^FS
^FO360,095^AAN,15,12^FD{CUSTOMERS.CUST_ADDR1}^FS

所以,如果这是表中唯一的一行,我想回复:

{CUSTOMERS.CUST_NAME}
{CUSTOMERS.CUST_ADDR1}

2 个答案:

答案 0 :(得分:5)

您提供的数据示例表明这是一行,但已将其显示为两个不同的行。所以这个例子基于你的话。

 -- Sample of data from your question + extra row for the sake of demonstration
 -- id column is added to distinguish the rows(I assume you have one)
  with t1(id, col) as( 
    select 1, '^FO360,065^AEN,25,10^FD{CUSTOMERS1.CUST_NAME}^FS^FO360,095^AAN,15,12^FD{CUSTOMERS1.CUST_ADDR1}^FS' from dual union all
    select 2, '^FO360,065^AEN,25,10^FD{CUSTOMERS2.CUST_NAME}^FS^FO360,095^AAN,15,12^FD{CUSTOMERS2.CUST_ADDR2}^FS' from dual
  ),
  cnt(c) as(
    select level
      from (select max(regexp_count(col, '{\w+.\w+}')) as o_c
              from t1
            ) z
     connect by level <= z.o_c
  )
  select t1.id, listagg(regexp_substr(t1.col, '{\w+.\w+}', 1, cnt.c)) within group(order by t1.id) res
    from t1
   cross join cnt
   group by t1.id

结果:

    ID   RES
    ---------------------------------------------------------
     1   {CUSTOMERS1.CUST_ADDR1}{CUSTOMERS1.CUST_NAME}
     2   {CUSTOMERS2.CUST_ADDR2}{CUSTOMERS2.CUST_NAME}

根据问题的@a_horse_with_no_name comment,实际上,更换其他与模式不匹配的内容要简单得多。这是一个例子:

 with t1(col) as(
    select '^FO360,065^AEN,25,10^FD{CUSTOMERS.CUST_NAME}^FS^FO360,095^AAN,15,12^FD{CUSTOMERS.CUST_ADDR1}^FS' from dual
 )
 select regexp_replace(t1.col, '({\w+.\w+})|.', '\1') res
  from t1

结果:

RES
-------------------------------------------
{CUSTOMERS.CUST_NAME}{CUSTOMERS.CUST_ADDR1} 

答案 1 :(得分:3)

我认为没有。你应该写一些PL / SQL来让其他人匹配令牌。我最好的建议是使用流水线功能。

首先,创建一个类型:

create type strings as table of varchar2(200);

然后功能:

CREATE OR REPLACE function let_me_show
return strings PIPELINED as
   l_n number;
   l_r varchar2(200);
begin
   for r_rec in
      ( SELECT commands
        FROM MYTABLE )
   loop
      l_n := 1;
      l_r := REGEXP_SUBSTR(r_rec.COMMANDS,'\{\w+\.\w+\}', 1, l_n);
      while l_r is not null
      loop
         pipe row(l_r);
         l_n := l_n + 1;
         l_r := REGEXP_SUBSTR(r_rec.COMMANDS,'\{\w+\.\w+\}', 1, l_n);         
      end loop;       
   end loop;
end;

现在您可以使用该函数返回结果:

select *
from table(let_me_show())