2013-01-08 86 views
4

我有一個包含名爲COMMANDS的VARCHAR2列的表。返回Oracle中正則表達式的所有匹配項

本專欄中的數據是一堆難以閱讀的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} 
+1

什麼?這應該在結果中留下所有的發生。 –

+0

@a_horse_with_no_name同意。將需要更少的代碼。 –

回答

4

已爲您數據樣本表示這是一行,但已將其呈現爲兩行不同的行。所以這個例子基於你的話。

-- 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 

結果:

有關使用REGEXP_REPLACE來代替一切,它*不*有一個空字符串匹配的模式
RES 
------------------------------------------- 
{CUSTOMERS.CUST_NAME}{CUSTOMERS.CUST_ADDR1} 
+0

謝謝 - 這給了我想要的東西(在添加了一個獨特的子句並擺脫了listagg和分組之後)。 – Mike

+0

我想過替換與模式不匹配的東西,但後來我終於在行中重複了許多次令牌,並且仍然難以篩選。第一種解決方案讓我可以獲得所有行使用的令牌的清單。 – Mike

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()) 
相關問題