你的赏金很高,所以我会全面地试图解决它。
你在正则表达式处理中做出了错误的假设。
- Oracle不兼容Perl正则表达式,而是与POSIX兼容。 它将其对Perl的支持描述为“受Perl影响”
- 在Oracle中使用Perl的"*?"存在内在的语法冲突,如果您像我一样阅读该参考文献,Oracle合法地选择了POSIX用法
- 您对Perl如何处理“*?”的描述并不完全正确。
这是我们讨论过的选项的混搭。 该问题的关键在于第30个案例。
情况 源 文本 结果 来自谁
------- ------------------------------- ------------------ ----------------- -------------------------------------------------- --------------
1 Egor的原始源字符串 A=1,B=2,C=3, .*B=.*?, Egor的原始模式“不起作用” A=1,B=2,C=3,
2 Egor的原始源字符串 A=1,B=2,C=3, .*B=.?, Egor的“工作正常” A=1,B=2,
3 Egor的原始源字符串 A=1,B=2,C=3, .*B=.+?, Old Pro评论1形式2 A=1,B=2,
4 Egor的原始源字符串 A=1,B=2,C=3, .+B=.*?, Old Pro评论1形式1 A=1,B=2,
5 Egor的原始源字符串 A=1,B=2,C=3, .*B=.{0,}?, Old Pro评论2 A=1,B=2,
6 Egor的原始源字符串 A=1,B=2,C=3, [^B]*B=[^Bx]*?, Old Pro答案形式1“好” A=1,B=2,
7 Egor的原始源字符串 A=1,B=2,C=3, [^B]*B=[^B]*?, Old Pro答案形式2“坏” A=1,B=2,C=3,
8 Egor的原始源字符串 A=1,B=2,C=3, (.)*B=(.)*?, TBone答案形式1 A=1,B=2,
9 TBone答案示例2 1_@_2_a_3_@_4_a (\w)*?@(\w)* TBone答案示例2形式1 1_@_2_a_3_
10 TBone答案示例2 1_@_2_a_3_@_4_a (\w)*@(\w)*? TBone答案示例2形式2 1_@
30 Egor的原始源字符串 A=1,B=2,C=3, .*B=(.)*?, Schemaczar变体以强制Perl操作 A=1,B=2,
31 Egor的原始源字符串 A=1,B=2,C=3, .*B=(.*)?, Schemaczar的Egor变体以强制POSIX A=1,B=2,C=3,
32 Egor的原始源字符串 A=1,B=2,C=3, .*B=.*{0,1} Schemaczar应用Egor的“非贪婪” A=1,B=2,C=3,
33 Egor的原始源字符串 A=1,B=2,C=3, .*B=(.)*{0,1} Schemaczar的另一种Egor“非贪婪”变体 A=1,B=2,C=3,
我非常确定CASE 30就是你想要写的-也就是说,你认为"*?"比"*"本身有更强的关联性。我猜Perl是这样的,但对于Oracle(以及可能是规范的POSIX)RE,"*?"的优先级和结合性低于"*"。因此,Oracle将其读作"(.*)?"(case 31),而Perl将其读作"(.)*?",也就是case 30。
请注意,案例32和33表明"*{0,1}"不像"*?"那样工作。
请注意,Oracle REGEXP与LIKE的工作方式不同,即它不要求匹配模式覆盖整个测试字符串。使用“^”开头和“$”结尾的标记也可能会对此有所帮助。
我的脚本:
SET SERVEROUTPUT ON
<<DISCREET_DROP>> begin
DBMS_OUTPUT.ENABLE;
for dropit in (select 'DROP TABLE ' || TABLE_NAME || ' CASCADE CONSTRAINTS' AS SYNT
FROM TABS WHERE TABLE_NAME IN ('TEST_PATS', 'TEST_STRINGS')
)
LOOP
DBMS_OUTPUT.PUT_LINE('Dropping via ' || dropit.synt);
execute immediate dropit.synt;
END LOOP;
END DISCREET_DROP;
/
CREATE TABLE TEST_PATS
( RE VARCHAR2(2000),
FROM_WHOM VARCHAR2(50),
PAT_GROUP VARCHAR2(50),
PAT_ORDER NUMBER(9,0)
) ;
/
CREATE TABLE TEST_STRINGS
( TEXT VARCHAR2(2000),
SRC VARCHAR2(200),
TEXT_GROUP VARCHAR2(50),
TEXT_ORDER NUMBER(9,0)
) ;
/
CREATE OR REPLACE FORCE VIEW REGEXP_TESTER_V (CASE_NUMBER, SRC, TEXT, RE, FROM_WHOM, RESULT) AS
select pat_order as case_number,
src, text, re, from_whom,
regexp_substr (text, re) as result
from test_pats full outer join test_strings on (text_group = pat_group)
order by pat_order, text_order;
/
REM INSERTING into TEST_PATS
SET DEFINE OFF;
Insert into TEST_PATS (RE,FROM_WHOM,PAT_GROUP,PAT_ORDER) values ('.*B=.*?,','Egor''s original pattern "doesn''t work"','Egor',1);
Insert into TEST_PATS (RE,FROM_WHOM,PAT_GROUP,PAT_ORDER) values ('.*B=.?,','Egor''s "works correctly"','Egor',2);
Insert into TEST_PATS (RE,FROM_WHOM,PAT_GROUP,PAT_ORDER) values ('.*B=(.)*?,','Schemaczar Variant to force Perl operation','Egor',30);
Insert into TEST_PATS (RE,FROM_WHOM,PAT_GROUP,PAT_ORDER) values ('.*B=(.*)?,','Schemaczar Variant of Egor to force POSIX','Egor',31);
Insert into TEST_PATS (RE,FROM_WHOM,PAT_GROUP,PAT_ORDER) values ('.*B=.*{0,1}','Schemaczar Applying Egor''s ''non-greedy''','Egor',32);
Insert into TEST_PATS (RE,FROM_WHOM,PAT_GROUP,PAT_ORDER) values ('.*B=(.)*{0,1}','Schemaczar Another variant of Egor''s "non-greedy"','Egor',33);
Insert into TEST_PATS (RE,FROM_WHOM,PAT_GROUP,PAT_ORDER) values ('[^B]*B=[^Bx]*?,','Old Pro answer form 1 "good"','Egor',6);
Insert into TEST_PATS (RE,FROM_WHOM,PAT_GROUP,PAT_ORDER) values ('[^B]*B=[^B]*?,','Old Pro answer form 2 "bad"','Egor',7);
Insert into TEST_PATS (RE,FROM_WHOM,PAT_GROUP,PAT_ORDER) values ('.*B=.+?,','Old Pro comment 1 form 2','Egor',3);
Insert into TEST_PATS (RE,FROM_WHOM,PAT_GROUP,PAT_ORDER) values ('.*B=.{0,}?,','Old Pro comment 2','Egor',5);
Insert into TEST_PATS (RE,FROM_WHOM,PAT_GROUP,PAT_ORDER) values ('.+B=.*?,','Old Pro comment 1 form 1','Egor',4);
Insert into TEST_PATS (RE,FROM_WHOM,PAT_GROUP,PAT_ORDER) values ('(.)*B=(.)*?,','TBone answer form 1','Egor',8);
Insert into TEST_PATS (RE,FROM_WHOM,PAT_GROUP,PAT_ORDER) values ('(\w)*?@(\w)*','TBone answer example 2 form 1','TBone',9);
Insert into TEST_PATS (RE,FROM_WHOM,PAT_GROUP,PAT_ORDER) values ('(\w)*@(\w)*?','TBone answer example 2 form 2','TBone',10);
REM INSERTING into TEST_STRINGS
SET DEFINE OFF;
Insert into TEST_STRINGS (TEXT,SRC,TEXT_GROUP,TEXT_ORDER) values ('A=1,B=2,C=3,','Egor''s original source string','Egor',1);
Insert into TEST_STRINGS (TEXT,SRC,TEXT_GROUP,TEXT_ORDER) values ('1_@_2_a_3_@_4_a','TBone answer example 2','TBone',2);
COLUMN SRC FORMAT A50 WORD_WRAP
COLUMN TEXT FORMAT A50 WORD_WRAP
COLUMN RE FORMAT A50 WORD_WRAP
COLUMN FROM_WHOM FORMAT A50 WORD_WRAP
COLUMN RESULT FORMAT A50 WORD_WRAP
SELECT * FROM REGEXP_TESTER_V;
'.+B=.*?,'
或者'.*B=.+?,'
代替。 - Old Pro.*B=.{0,}?,
。 - Old Pro?
的含义与Perl RE中相同 :-) - Egor Skriptunoff