我在MySQL和Oracle中执行了相同的语句,但它们返回了不同的结果。正则表达式“/?“的意思是返回零个或多个“/",但为什么MySQL会返回一个“products”,是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;
}
1条答案
按热度按时间83qze16e1#
问题不在于
/?
,而在于前面的\.?
。在MySQL中,正则表达式语法文档指出:
若要在正则表达式中使用特殊字符的文本示例,请在其前面加上两个反斜杠(
\
)字符。MySQL解析器解释其中一个反斜杠,正则表达式库解释另一个反斜杠。例如,要匹配包含特殊+字符的字符串1+2,只有以下正则表达式中的最后一个才是正确的:所以:
输出:
| 单斜线|双斜线|字符类|
| --|--|--|
| http://www.example.com/products | http://www.example.com/ | http://www.example.com/ |
在第一个模式中,
\.
与.
相同,并且匹配任何字符,因此[[:alnum:]]+\.?
匹配www.
,然后example.
,然后com/
,然后products
第4次出现。要只匹配.
字符,您需要\\.
或[.]
。MySQL fiddle
在Oracle中,您希望使用
\.
或[.]
而不是\\.
来匹配.
字符。(因此,如果您想在两种SQL方言中使用相同的表达式,请使用http://([[:alnum:]]+[.]?){3,4}/?
。Oracle fiddle