我要获取的是列文本中某些字符之间的部分(准确地说是$$
),但诀窍是这些字符可能会出现两次以上(但始终会出现两次)比必须像$$xxx$$ ... $$yyy$$
的2个多),我需要分别获取它们。
当我尝试此操作时,如果模式仅出现一次,那就没问题了:
regexp_substr(txt,'\$\$(.*)\$\$',1,1,null,1)
但是可以说列文本为:$$xxx$$ ... $$yyy$$
然后它给了我:xxx$$ ... $$yyy
但是我需要两个让它们分开放置:
xxx
yyy
我做不到,怎么办?
答案 0 :(得分:3)
您可以使用与第一次匹配的递归查询,然后将其从字符串中删除,以进行递归查询的下一次迭代。
假设您的表和列分别称为tbl
和txt
:
with cte(match, txt) as (
select regexp_substr(txt,'\$\$(.*?)\$\$', 1, 1, null, 1),
regexp_replace(txt,'\$\$(.*?)\$\$', '', 1, 1)
from tbl
where regexp_like(txt,'\$\$(.*?)\$\$')
union all
select regexp_substr(txt,'\$\$(.*?)\$\$', 1, 1, null, 1),
regexp_replace(txt,'\$\$(.*?)\$\$', '', 1, 1)
from cte
where regexp_like(txt,'\$\$(.*?)\$\$')
)
select match from cte
答案 1 :(得分:1)
还可以使用CONNECT BY来循环遍历由双美元符号包围的元素,并返回内部的数据(第二个分组)。此方法处理NULL元素(ID 7,元素2),并且由于正则表达式从左向右移动时会消耗美元符号,因此组之间的字符不会错误匹配。
SQL> with tbl(id, txt) as (
select 1, '$$xxx$$' from dual union all
select 2, '$$xxx$$ ... $$yyy$$' from dual union all
select 3, '' from dual union all
select 4, '$$xxx$$abc$$yyy$$' from dual union all
select 5, '$$xxx$$ ... $$yyy$$ ... $$www$$ ... $$zzz$$' from dual union all
select 6, '$$aaa$$$$bbb$$$$ccc$$$$ddd$$' from dual union all
select 7, '$$aaa$$$$$$$$ccc$$$$ddd$$' from dual
)
select id, level, regexp_substr(txt,'(\$\$(.*?)\$\$)',1,level,null,2) element
from tbl
connect by regexp_substr(txt,'(\$\$(.*?)\$\$)',1,level) is not null
and prior txt = txt
and prior sys_guid() is not null
order by id, level;
ID LEVEL ELEMENT
---------- ---------- -------------------------------------------
1 1 xxx
2 1 xxx
2 2 yyy
3 1
4 1 xxx
4 2 yyy
5 1 xxx
5 2 yyy
5 3 www
5 4 zzz
6 1 aaa
6 2 bbb
6 3 ccc
6 4 ddd
7 1 aaa
7 2
7 3 ccc
7 4 ddd
18 rows selected.
SQL>