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

Sql 返回Oracle中正则表达式的所有匹配项,sql,regex,oracle,oracle11g,oracle11gr2,Sql,Regex,Oracle,Oracle11g,Oracle11gr2,我有一个表,其中包含一个名为COMMANDS的VARCHAR2列 此列中的数据是一组难以读取的ZPL代码,这些代码将被发送到标签打印机,在ZPL中有几个{TABLE.column}形式的令牌 我想要一个漂亮的列表,列出在命令中找到的所有不同的{TABLE.COLUMN}标记。我编写了以下正则表达式以匹配令牌格式: SELECT REGEXP_SUBSTR(COMMANDS,'\{\w+\.\w+\}') FROM MYTABLE; 正则表达式可以工作,但每行只返回第一个匹配的令牌。是否有方法返

我有一个表,其中包含一个名为COMMANDS的VARCHAR2列

此列中的数据是一组难以读取的ZPL代码,这些代码将被发送到标签打印机,在ZPL中有几个{TABLE.column}形式的令牌

我想要一个漂亮的列表,列出在命令中找到的所有不同的{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}

我想没有。您应该编写一些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())

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

 -- 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
根据问题中没有名字的@a_horse_,真的,替换其他与模式不匹配的东西要简单得多。以下是一个例子:

 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} 

使用regexp_replace将与模式不匹配的所有内容替换为空字符串怎么样?这应该会在结果中留下所有发生的事情。@a_horse_,没有名字,同意。将需要更少的代码。谢谢——这让我得到了我想要的(在添加了一个distinct子句并去掉了listag和grouping之后)。我曾想过替换与模式不匹配的内容,但最终我得到了跨行重复多次的标记,而且仍然很难筛选。第一个解决方案使我能够获得所有行中使用的令牌的不同列表。
RES
-------------------------------------------
{CUSTOMERS.CUST_NAME}{CUSTOMERS.CUST_ADDR1}