Oracle
 sql >> Datenbank >  >> RDS >> Oracle

Warum funktioniert ein nicht-gieriger Quantifizierer manchmal nicht in Oracle Regex?

Es ist ein FEHLER!

Sie haben Recht, dass in Perl 'A=1,B=2,C=3,' =~ /.*B=.*?,/; print $& drucken druckt A=1,B=2,

Worüber Sie gestolpert sind, ist ein Fehler, der immer noch in Oracle Database 11g R2 vorhanden ist. Wenn genau dasselbe Atom eines regulären Ausdrucks (einschließlich des Quantifizierers, aber ohne den Giermodifikator) zweimal in einem regulären Ausdruck vorkommt, haben beide Vorkommen die Gier, die durch das erste Auftreten angegeben wird, unabhängig von der Gier, die durch das zweite angegeben wird. Dass dies ein Fehler ist, wird durch diese Ergebnisse deutlich demonstriert (hier ist „das exakt gleiche reguläre Ausdrucksatom“ [^B]* ):

SQL> SELECT regexp_substr('A=1,B=2,C=3,', '[^B]*B=[^Bx]*?,') as good FROM dual;

GOOD
--------
A=1,B=2,

SQL> SELECT regexp_substr('A=1,B=2,C=3,', '[^B]*B=[^B]*?,') as bad FROM dual;

BAD
-----------
A=1,B=2,C=3,

Der einzige Unterschied zwischen den beiden regulären Ausdrücken besteht darin, dass der „gute“ Ausdruck „x“ als mögliche Übereinstimmung in der zweiten Übereinstimmungsliste ausschließt. Da „x“ nicht in der Zielzeichenfolge vorkommt, sollte das Ausschließen keinen Unterschied machen, aber wie Sie sehen können, macht das Entfernen des „x“ einen großen Unterschied. Das muss ein Fehler sein.

Hier sind einige weitere Beispiele aus Oracle 11.2:(SQL Fiddle mit noch mehr Beispielen )

SELECT regexp_substr('A=1,B=2,C=3,', '.*B=.*?,')  FROM dual; =>  A=1,B=2,C=3,
SELECT regexp_substr('A=1,B=2,C=3,', '.*B=.*,')   FROM dual; =>  A=1,B=2,C=3,
SELECT regexp_substr('A=1,B=2,C=3,', '.*?B=.*?,') FROM dual; =>  A=1,B=2,
SELECT regexp_substr('A=1,B=2,C=3,', '.*?B=.*,')  FROM dual; =>  A=1,B=2,
-- Changing second operator from * to +
SELECT regexp_substr('A=1,B=2,C=3,', '.*B=.+?,')  FROM dual; =>  A=1,B=2,
SELECT regexp_substr('A=1,B=2,C=3,', '.*B=.+,')   FROM dual; =>  A=1,B=2,C=3,
SELECT regexp_substr('A=1,B=2,C=3,', '.+B=.+,')   FROM dual; =>  A=1,B=2,C=3,
SELECT regexp_substr('A=1,B=2,C=3,', '.+?B=.+,')  FROM dual; =>  A=1,B=2,

Das Muster ist konsistent:Die Gier des ersten Vorkommens wird für das zweite Vorkommen verwendet, ob es sein sollte oder nicht.