Oracle 和 Mysql 中的 regexp_substr

问题描述 投票:0回答:1

我在MySQL和Oracle中执行了相同的语句,但它们返回了不同的结果。正则表达式 ”/?”意思是返回零个或多个“/”,但是为什么MySQL会返回一个“产品”,是MySQL实现错误吗?

SELECT
  REGEXP_SUBSTR('http://www.example.com/products',
                'http://([[:alnum:]]+\.?){3,4}/?') "REGEXP_SUBSTR"
  FROM DUAL;

Oracle Output:
REGEXP_SUBSTR
http://www.example.com/

MySQL Output:
REGEXP_SUBSTR
http://www.example.com/products

我查询了Oracle和MySQL的文档,他们对“?”的定义感兴趣,是匹配零个或一个字符。MySQL说他们实现了ICU库的常规支持。但是ICU的输出是“http:// www.example.com/”。

int main(int argc, char *argv[]) {
    uint32_t flags = 0;
    flags |= UREGEX_UNIX_LINES;
    flags |= UREGEX_CASE_INSENSITIVE;
    const char *c_source_char = "http://www.example.com/products";
    const char *c_pat_char = "http://([[:alnum:]]+\\.?){3}/?";;
    UErrorCode status = U_ZERO_ERROR;
    URegularExpression *regexp = uregex_openC(c_pat_char, 0, NULL, &status);
    UChar ustr[100];
    u_uastrcpy(ustr, c_source_char);
    uregex_setText(regexp, ustr, -1, &status);
    if (uregex_find(regexp, 0, &status)) {
        int32_t start = uregex_start(regexp, 0, &status);
        int32_t end = uregex_end(regexp, 0, &status);
        if(end - start > 0) {
            std::string res(c_source_char+start, c_source_char+end);
            std::cout << res << std::endl;
        }
        
        printf("Found match at %d-%d\n", start, end);
    }
    uregex_close(regexp);
    return 0;
}
mysql oracle icu regexp-substr
1个回答
0
投票

问题不在于

/?
,而在于前面的
\.?

在 MySQL 中,正则表达式语法文档指出:

要在正则表达式中使用特殊字符的文字实例,请在其前面添加两个反斜杠 (

\
) 字符。 MySQL 解析器解释其中一个反斜杠,正则表达式库解释另一个。例如,要匹配包含特殊字符“+”的字符串 1+2,只有以下正则表达式中的最后一个才是正确的:

mysql> SELECT REGEXP_LIKE('1+2', '1+2');                       -> 0
mysql> SELECT REGEXP_LIKE('1+2', '1\+2');                      -> 0
mysql> SELECT REGEXP_LIKE('1+2', '1\\+2');                     -> 1

所以:

SELECT REGEXP_SUBSTR(
         'http://www.example.com/products',
         'http://([[:alnum:]]+\.?){3,4}/?'
       ) AS single_slash,
       REGEXP_SUBSTR(
         'http://www.example.com/products',
         'http://([[:alnum:]]+\\.?){3,4}/?'
       ) AS double_slash,
       REGEXP_SUBSTR(
         'http://www.example.com/products',
         'http://([[:alnum:]]+[.]?){3,4}/?'
       ) AS character_class
FROM   DUAL;

输出:

单斜杠 双斜杠 角色_类别
http://www.example.com/products http://www.example.com/ http://www.example.com/

在第一个模式中,

\.
.
相同,并且匹配任何字符,因此
[[:alnum:]]+\.?
匹配
www.
然后
example.
然后
com/
然后
products
第四次出现。要仅匹配
.
字符,您需要
\\.
[.]

小提琴

© www.soinside.com 2019 - 2024. All rights reserved.