あなたは本当に素晴らしい報奨金を手に入れたので、私はそれを包括的に釘付けにしようとします.
正規表現の処理で間違った仮定をしています。
- Oracle は Perl 正規表現と互換性がなく、POSIX と互換性があります。Perlのサポートを「Perl-Influenced」と説明しています
- Perl の「*?」の使用に関して、固有の構文の競合があります。オラクルでは、私のやり方でそのリファレンスを読んだ場合、オラクルは合法的にPOSIXの使用法を選択します
- perl が "*?" をどのように処理するかについての説明 は正しくありません。
以下は、これまでに説明したオプションのマッシュアップです。この問題の鍵はケース 30 あたりにあります
CASE SRC テキスト RE FROM_WHOM 結果
------- ---------------------------------------------- ------------ ------ ----------------- --------------------------- ----------------------- --------------
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=.*?, オールド プロ コメント 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 answer form 1 "good" A=1,B=2,
7 Egor の元のソース文字列 A=1,B=2,C=3, [^B]*B=[^B]*?, Old Pro answer form 2 "bad" 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=(.)*?, Perl 操作を強制する Schemaczar バリアント A=1,B=2,
31 Egor の元のソース文字列 A=1,B=2,C=3, .*B=(.*)?, POSIX A=1,B=2,C=3 を強制するための Egor のスキーマバリアント
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 は「(.*)?」と読み取ります。(ケース 31) 一方、Perl はそれを "(.)*?" として読み取ります。つまり、ケース 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;
/
--------------------------------------------------------
-- DDL for Table TEST_PATS
--------------------------------------------------------
CREATE TABLE TEST_PATS
( RE VARCHAR2(2000),
FROM_WHOM VARCHAR2(50),
PAT_GROUP VARCHAR2(50),
PAT_ORDER NUMBER(9,0)
) ;
/
--------------------------------------------------------
-- DDL for Table TEST_STRINGS
--------------------------------------------------------
CREATE TABLE TEST_STRINGS
( TEXT VARCHAR2(2000),
SRC VARCHAR2(200),
TEXT_GROUP VARCHAR2(50),
TEXT_ORDER NUMBER(9,0)
) ;
/
--------------------------------------------------------
-- DDL for View REGEXP_TESTER_V
--------------------------------------------------------
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;