Sql 返回Oracle中正则表达式的所有匹配项
我有一个表,其中包含一个名为COMMANDS的VARCHAR2列 此列中的数据是一组难以读取的ZPL代码,这些代码将被发送到标签打印机,在ZPL中有几个{TABLE.column}形式的令牌 我想要一个漂亮的列表,列出在命令中找到的所有不同的{TABLE.COLUMN}标记。我编写了以下正则表达式以匹配令牌格式: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; 正则表达式可以工作,但每行只返回第一个匹配的令牌。是否有方法返
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}