MySQL REGEXP正则表达式匹配异常及括号使用疑问咨询
MySQL REGEXP正则表达式匹配异常及括号使用疑问咨询
嗨,我来帮你梳理清楚这个问题的来龙去脉哈!
首先先解决你最困惑的点:为什么第二个正则表达式 SELECT * FROM my_tableWHEREmy_field REGEXP '[\[|,]24[,|\]]' 返回空结果?
这其实和MySQL正则表达式的引擎特性有关——你在测试工具里用的是PCRE风格的正则,而MySQL(尤其是8.0之前的版本)默认采用的是POSIX标准的正则实现,两者在字符组的解析逻辑上有细微差异。
你第二个正则里的末尾字符组 [,|\]],在MySQL的POSIX正则规则里,]如果要在字符组里表示字面量,必须放在字符组的最开头,否则会被直接解析为字符组的结束标记。你把]放在了字符组的最后,导致这个字符组实际被解析成了只匹配,或者|(第一个]就结束了字符组,后面的内容直接被忽略),所以这个正则根本没法匹配到24后面跟着]的情况,自然就返回空结果啦!
而第一个正则能正常工作,正是因为你把]放在了字符组的开头[\]|,],MySQL能正确识别这是要匹配]的字面量,所以所有测试场景都能命中。
接下来解答你关于括号的疑问:MySQL是支持括号()的,但要分版本看规则:
- 在MySQL 8.0及以后的版本,REGEXP已经切换到了RE2引擎,支持PCRE风格的语法,括号可以直接用来分组,不需要额外转义;
- 而在MySQL 5.7及更早的版本,使用的是POSIX基本正则表达式,括号
()默认被当作普通字面量字符,如果要用来做分组逻辑,必须转义成\(和\)才行。你在测试工具里直接用(\[|,)24(\]|,)能工作,是因为工具用的是PCRE引擎,不需要转义括号,但放到老版本MySQL里就会把(和)当成普通字符去匹配,自然就匹配不到目标内容了。
最后给你几个修正后的可用写法,适配不同场景:
- 兼容低版本MySQL的写法,同时规避字符组的解析问题:
这里把SELECT * FROM `my_table` WHERE `my_field` REGEXP '([\\[|,]24[|,\\]])']转义成\\](因为MySQL字符串里\本身也需要转义),同时用转义后的括号\\(和\\)来实现分组(其实你这个场景里分组不是必须的,去掉也能正常工作)。 - 更简洁的通用写法,去掉字符组里多余的
|(字符组本身就是“或”的逻辑,[[,]就可以匹配[或者,):
这个写法在全版本MySQL里都能正常工作,完美覆盖你所有的测试场景。SELECT * FROM `my_table` WHERE `my_field` REGEXP '[[,]24[,\]]'
内容来源于stack exchange




