如何在 REGEXP 中转义 MySQL 中的星号 (*)
Posted
技术标签:
【中文标题】如何在 REGEXP 中转义 MySQL 中的星号 (*)【英文标题】:How to escape asterisk (*) in MySQL in a REGEXP 【发布时间】:2021-12-31 14:48:35 【问题描述】:我尝试在 mysql 中将关键字与REGEXP
匹配如下:
-- Match "fitt*", the asterisk "*" is expected to be matched as-is
> select 'aaaa fitt* bbb' regexp '[[:<:]]fitt\*[[:>:]]'; -- return 1, ok
> select 'aaaa fitttttt* bbb' regexp '[[:<:]]fitt\*[[:>:]]'; -- return 1 as well, but should return 0
> select 'aaaa fitt* bbb' regexp '[[:<:]]fitt\\*[[:>:]]'; -- return 0, failed
如何转义星号 (*
) 以完全匹配字符 *
?
【问题讨论】:
问题不在于星号,而在于[[:>:]]
。那只匹配单词边界,但*
和空格之间没有单词边界,因为*
不是单词字符。
@Barmar 谢谢。但是如何将fitt*
这个词与REGEXP匹配呢?
我根据@Barmar 和我自己之间的辩论更改了标题。
【参考方案1】:
\\*
是匹配星号的正确方法。但是[[:>:]]
不会在它之后匹配,因为它只匹配单词字符和非单词字符,而*
不是单词字符。相反,您需要在那里显式匹配一个非单词字符。您还需要一个替代行尾,因为这是另一种类型的单词边界。
> select 'aaaa fitt* bbb' regexp '[[:<:]]fitt\\*([^[:alnum:]]|$)'; -- returns 1
> select 'aaaa fitttttt* bbb' regexp '[[:<:]]fitt\\*([^[:alnum:]]|$)'; -- returns 0
另一种明确匹配星号的方法是将其放入字符类中。
> select 'aaaa fitt* bbb' regexp '[[:<:]]fitt[*]([^[:alnum:]]|$)'; -- returns 1
> select 'aaaa fitttttt* bbb' regexp '[[:<:]]fitt[*]([^[:alnum:]]|$)'; -- returns 0
【讨论】:
没有。\\*
表示零个或多个反斜杠。您的测试碰巧 工作,因为它发现零个反斜杠,然后是 *
,它不是“alnum”。
@RickJames 第一个反斜杠转义了字符串中的第二个反斜杠。由此产生的反斜杠转义了正则表达式中的*
。
如果我在被测试的字符串中放了一个反斜杠,它就不匹配了。
字符串中的反斜杠是否被转义了? SELECT 'a\b' REGEXP 'a.b', 'a\\b' REGEXP 'a.b';
--> 0, 1.
@RickJames select 'aaaa fitt\\* bbb' regexp '[[:<:]]fitt\\*([^[:alnum:]]|$)';
-> 0`【参考方案2】:
可能有 3 个问题:
第 1 项:标题问题的答案是以下之一:
\\* (in the regexp)
[*]
第 2 项:\\\\*
可能如果您来自某个客户端,该客户端首先取消转义反斜杠,然后再将其提供给 MySQL,而 MySQL 仍然需要反斜杠。但是,正如所写(没有任何客户端代码),\\\\*
被视为零个或多个反斜杠。
第 3 项:@Barmar 的回答集中在为什么 [[:>:]]
不正确。
【讨论】:
\\*
如果您在查询中逐字写入字符串,则需要,因为 MySQL 本身首先会取消反斜杠。
如果您使用的客户端编程语言也无法转义,则需要再次加倍,例如$sql = "SELECT 'aaaa fitt* bbb' regexp '[[:<:]]fitt\\\\*([^[:alnum:]]|$)'";
在 php 中。
@Barmar 和 Zelong -- 我在 mysql 命令行工具中进行测试;你在测试什么?以上是关于如何在 REGEXP 中转义 MySQL 中的星号 (*)的主要内容,如果未能解决你的问题,请参考以下文章