我想替换Oracle中REGEXP_REPLACE中找到的值。我使用regex101.com工具来调试我的正则表达式,它也突出了结果,但是如果我将这个表达式放入我的select中,它什么都不做......它不会替换我想要的字符串。所以,我的问题是,为什么这种模式在Oracle PL / SQL中是错误的?
select REGEXP_REPLACE('SOME XML DATAS', '/(?<=</FIRST_TAG>)(.*)(?=</LAST_TAG>)/s', '<REPLACE_TAG xsi:nil="1"/>') from dual
如您所见,我在两个结束标签之间进行搜索。
示例XML:
<?xml version='1.0' encoding='UTF-8'?>
<LAST_TAG xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns="urn:bla-bla-bla">
<DEFAULT_LANGUAGE>en</DEFAULT_LANGUAGE>
<DEBUG>0</DEBUG>
<DEBUG_LEVEL>MEDIUM</DEBUG_LEVEL>
<DEBUG_FILE>bla-bla.log</DEBUG_FILE>
<FIRST_TAG>
<LOGICAL_PRINTER>
<ID>PRINTER1</ID>
<PHYSICAL_PRINTER>Dummy_Printer</PHYSICAL_PRINTER>
</LOGICAL_PRINTER>
<LOGICAL_PRINTER>
<ID>PRINT01</ID>
<PHYSICAL_PRINTER>PRINT01</PHYSICAL_PRINTER>
</LOGICAL_PRINTER>
<LOGICAL_PRINTER>
<ID>PRINT012</ID>
<PHYSICAL_PRINTER>PRINT02</PHYSICAL_PRINTER>
</LOGICAL_PRINTER>
<LOGICAL_PRINTER>
<ID>PRINT015</ID>
<PHYSICAL_PRINTER>PRINT05</PHYSICAL_PRINTER>
</LOGICAL_PRINTER>
<LOGICAL_PRINTER>
<ID>PRINT019</ID>
<PHYSICAL_PRINTER>PRINT019</PHYSICAL_PRINTER>
</LOGICAL_PRINTER>
<LOGICAL_PRINTER>
<ID>PRINT010</ID>
<PHYSICAL_PRINTER>PRINT010</PHYSICAL_PRINTER>
</LOGICAL_PRINTER>
<LOGICAL_PRINTER>
<ID>PRINT_ID01</ID>
<PHYSICAL_PRINTER>\\111.111.111.111\PRINT011</PHYSICAL_PRINTER>
</LOGICAL_PRINTER>
<LOGICAL_PRINTER>
<ID>PRINT_ID03</ID>
<PHYSICAL_PRINTER>\\111.111.111.111\PRINT013</PHYSICAL_PRINTER>
</LOGICAL_PRINTER>
<LOGICAL_PRINTER>
<ID>PRINT_ID04</ID>
<PHYSICAL_PRINTER>\\111.111.111.111\PRINT014</PHYSICAL_PRINTER>
</LOGICAL_PRINTER>
<LOGICAL_PRINTER>
<ID>PRINT_ID05</ID>
<PHYSICAL_PRINTER>\\111.111.111.111\PRINT015</PHYSICAL_PRINTER>
</LOGICAL_PRINTER>
<LOGICAL_PRINTER>
<ID>BUDCOLOR</ID>
<PHYSICAL_PRINTER>\\url\printer</PHYSICAL_PRINTER>
</LOGICAL_PRINTER>
<LOGICAL_PRINTER>
<ID>NAMENAME</ID>
<PHYSICAL_PRINTER>\\url\printer</PHYSICAL_PRINTER>
</LOGICAL_PRINTER>
</FIRST_TAG>
<LOCALE_LIST>
<LOCALE>
<DISPLAY_NAME>English (United States)</DISPLAY_NAME>
<COUNTRY>US</COUNTRY>
<LANGUAGE>en</LANGUAGE>
<VARIANT xsi:nil="1"/>
</LOCALE>
</LOCALE_LIST>
</LAST_TAG>
非常感谢!
答案 0 :(得分:2)
精细手册的相关部分:Using Regular Expressions in Database Applications。
我们的想法是匹配要替换的文本周围的文本,并使用反向引用来匹配替换字符串中的子表达式。
with data(id, str) as (
select 1, 'foo is bar' from dual union all
select 2, 'foo was bar' from dual union all
select 3, 'foo might be or might not be bar' from dual
)
select
id
,str
,regexp_replace(str, '^(foo).+(bar)$', '\1***\2') as str2
from data
;
OP示例数据的另一个示例。请注意使用match parameter n
:
'n'允许句点(。)(匹配任意字符)匹配换行符。如果省略此参数,则句点与换行符不匹配。
该参数是必需的,因为该字符串包含换行符号。以下示例将正确消除LOCALE_LIST
- 元素。 警告:请注意,建议您不要使用正则表达式操作字符串化XML。
with data(id, str) as (
select 1, q'[<?xml version='1.0' encoding='UTF-8'?>
<LAST_TAG xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns="urn:bla-bla-bla">
<DEFAULT_LANGUAGE>en</DEFAULT_LANGUAGE>
<FIRST_TAG>
<LOGICAL_PRINTER>
<ID>PRINTER1</ID>
<PHYSICAL_PRINTER>Dummy_Printer</PHYSICAL_PRINTER>
</LOGICAL_PRINTER>
</FIRST_TAG>
<LOCALE_LIST>
<LOCALE>
<DISPLAY_NAME>English (United States)</DISPLAY_NAME>
<VARIANT xsi:nil="1"/>
</LOCALE>
</LOCALE_LIST>
</LAST_TAG>]' from dual
)
select
id
,regexp_replace(str, '(.+</FIRST_TAG>).+(</LAST_TAG>)', '\1***\2', 1, 1, 'n') as str2
from data
;
答案 1 :(得分:0)
也许您尝试像xmldocument一样处理xml而不是像文本一样。
declare
v xmltype:= xmltype('<?xml version=''1.0'' encoding=''UTF-8''?>
<LAST_TAG xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance">
<DEFAULT_LANGUAGE>en</DEFAULT_LANGUAGE>
<DEBUG>0</DEBUG>
<DEBUG_LEVEL>MEDIUM</DEBUG_LEVEL>
<DEBUG_FILE>bla-bla.log</DEBUG_FILE>
<FIRST_TAG>
<LOGICAL_PRINTER>
<ID>PRINTER1</ID>
<PHYSICAL_PRINTER>Dummy_Printer</PHYSICAL_PRINTER>
</LOGICAL_PRINTER>
<LOGICAL_PRINTER>
<ID>PRINT01</ID>
<PHYSICAL_PRINTER>PRINT01</PHYSICAL_PRINTER>
</LOGICAL_PRINTER>
<LOGICAL_PRINTER>
<ID>PRINT012</ID>
<PHYSICAL_PRINTER>PRINT02</PHYSICAL_PRINTER>
</LOGICAL_PRINTER>
<LOGICAL_PRINTER>
<ID>PRINT015</ID>
<PHYSICAL_PRINTER>PRINT05</PHYSICAL_PRINTER>
</LOGICAL_PRINTER>
<LOGICAL_PRINTER>
<ID>PRINT019</ID>
<PHYSICAL_PRINTER>PRINT019</PHYSICAL_PRINTER>
</LOGICAL_PRINTER>
<LOGICAL_PRINTER>
<ID>PRINT010</ID>
<PHYSICAL_PRINTER>PRINT010</PHYSICAL_PRINTER>
</LOGICAL_PRINTER>
<LOGICAL_PRINTER>
<ID>PRINT_ID01</ID>
<PHYSICAL_PRINTER>\\111.111.111.111\PRINT011</PHYSICAL_PRINTER>
</LOGICAL_PRINTER>
<LOGICAL_PRINTER>
<ID>PRINT_ID03</ID>
<PHYSICAL_PRINTER>\\111.111.111.111\PRINT013</PHYSICAL_PRINTER>
</LOGICAL_PRINTER>
<LOGICAL_PRINTER>
<ID>PRINT_ID04</ID>
<PHYSICAL_PRINTER>\\111.111.111.111\PRINT014</PHYSICAL_PRINTER>
</LOGICAL_PRINTER>
<LOGICAL_PRINTER>
<ID>PRINT_ID05</ID>
<PHYSICAL_PRINTER>\\111.111.111.111\PRINT015</PHYSICAL_PRINTER>
</LOGICAL_PRINTER>
<LOGICAL_PRINTER>
<ID>BUDCOLOR</ID>
<PHYSICAL_PRINTER>\\url\printer</PHYSICAL_PRINTER>
</LOGICAL_PRINTER>
<LOGICAL_PRINTER>
<ID>NAMENAME</ID>
<PHYSICAL_PRINTER>\\url\printer</PHYSICAL_PRINTER>
</LOGICAL_PRINTER>
</FIRST_TAG>
<LOCALE_LIST>
<LOCALE>
<DISPLAY_NAME>English (United States)</DISPLAY_NAME>
<COUNTRY>US</COUNTRY>
<LANGUAGE>en</LANGUAGE>
<VARIANT xsi:nil="1"/>
</LOCALE>
</LOCALE_LIST>
</LAST_TAG>');
begin
v := v.deleteXML('/LAST_TAG/DEBUG_FILE/following-sibling::*','xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"').appendChildXML('/LAST_TAG',xmltype('<NEW_TAG/>'));
dbms_output.put_line(v.getClobVal());
end;