Đó là một BUG!
Bạn đúng rằng trong Perl, 'A=1,B=2,C=3,' =~ /.*B=.*?,/; print $&
bản in A=1,B=2,
Những gì bạn đã vấp phải là một lỗi vẫn tồn tại trong Cơ sở dữ liệu Oracle 11g R2. Nếu cùng một nguyên tử biểu thức chính quy giống hệt nhau (bao gồm bộ định lượng nhưng không bao gồm công cụ sửa đổi độ tham) xuất hiện hai lần trong một biểu thức chính quy, thì cả hai lần xuất hiện sẽ có độ tham được chỉ ra bởi lần xuất hiện đầu tiên bất kể độ tham được chỉ định bởi lần thứ hai. Đây là một lỗi đã được chứng minh rõ ràng bởi các kết quả này (ở đây, "nguyên tử biểu thức chính quy giống hệt nhau" là [^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,
Sự khác biệt duy nhất giữa hai biểu thức chính quy là biểu thức "tốt" loại trừ 'x' là một đối sánh có thể có trong danh sách đối sánh thứ hai. Vì 'x' không xuất hiện trong chuỗi mục tiêu, việc loại trừ nó sẽ không tạo ra sự khác biệt nào, nhưng như bạn có thể thấy, việc loại bỏ 'x' sẽ tạo ra sự khác biệt lớn. Đó phải là một lỗi.
Dưới đây là một số ví dụ khác từ Oracle 11.2:( SQL Fiddle với nhiều ví dụ hơn nữa )
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,
Mô hình nhất quán:lòng tham của lần xuất hiện đầu tiên được sử dụng cho lần xuất hiện thứ hai cho dù nó có nên hay không.