在MySQL中,当在需要“全字匹配”的文本字段中搜索关键字时,可以使用REGEXP和[[:&lt ;:]]和[[:>:]]字 - 边界标记:
SELECT name FROM tbl_name WHERE name REGEXP "[[:<:]]word[[:>:]]"
例如,当我们想要找到包含“europe”的所有文本字段时,使用
SELECT name FROM tbl_name WHERE name REGEXP "[[:<:]]europe[[:>:]]"
会返回“欧洲地图”,但不会返回“欧洲联盟”。
但是,当目标匹配单词包含“点字符”时,如“u.s.”,我该如何提交正确的查询?我尝试了以下查询,但没有一个看起来正确。
1
SELECT name FROM tbl_name WHERE name REGEXP "[[:<:]]u.s.[[:>:]]"
2
SELECT name FROM tbl_name WHERE name REGEXP "[[:<:]]u[.]s[.][[:>:]]"
3
SELECT name FROM tbl_name WHERE name REGEXP "[[:<:]]u\.s\.[[:>:]]"
当使用双反斜杠来转义特殊字符时,正如d'alar'cop所建议的那样,它返回空,即使表中有“u.s. congress”之类的内容
SELECT name FROM tbl_name WHERE name REGEXP "[[:<:]]u\\.s\\.[[:>:]]"
任何建议都表示赞赏!
答案 0 :(得分:10)
这个正则表达式做你想要的:
SELECT name
FROM tbl_name
WHERE name REGEXP '([[:blank:][:punct:]]|^)u[.]s[.]([[:punct:][:blank:]]|$)'
匹配u.s.
时,前面跟着:
然后是:
查看SQLFiddle的边缘情况,包括以上几点。
答案 1 :(得分:7)
谓词的基本问题是.
是一个非单词字符,任何非单词字符都会导致单词边界测试失败,如果它们遵循开始测试或在结束测试之前。您可以看到行为here。
为了使问题进一步复杂化,MySQL使用的正则表达式的风格非常有限。根据{{3}},MySQL使用Regular-Expressions.info,如果您阅读底部的POSIX-ERE图表,与其他版本相比,其功能非常少。
要解决您的问题,您必须创建一个新的正则表达式,它将替换单词边界的功能,以便它允许非单词字符成为边界的一部分。我提出了以下正则表达式:
(^|[^[:alnum:]_])YOUR_TEXT_HERE($|[^[:alnum:]_])
这相当于下面的标准正则表达式:
(^|[^a-zA-Z0-9_])YOUR_TEXT_HERE($|[^a-zA-Z0-9_])
正则表达式在文本的开头和结尾搜索非单词字符或字符串边界。 (^|[^[:alnum:]_])
匹配字符串的开头,字母数字字符或下划线。结束模式类似,只是它匹配字符串的结尾而不是开头。
该模式旨在最佳地匹配Regular Expression Flavor Comparisons:
中字边界的定义[Boundaries]分别匹配单词的开头和结尾。一个 word是一个字符序列,前面没有或 后跟单词字符。单词字符是字母数字 alnum 类中的字符或下划线。
使用上面的正则表达式,我想出了一个场景,我在开始和结束时测试一个包含非单词字符的字符串 - .u.s.
。我试着提出一套合理的测试项目。你可以看到结果
Regular Expressions in the MySQL manual
测试数据
test string not present: 'no match'
missing .'s: 'no us match'
missing last .: 'no u.s match'
missing first .: 'no us. match'
test start boundary word character: 'no.u.s.match'
test end boundary word character: 'no .u.s.match'
test boundaries word character: 'no.u.s.match'
test basic success case: 'yes .u.s. match'
test start boundary non-word character: 'yes !.u.s. match'
test end boundary non-word character: 'yes .u.s.! match'
test boundaries non-word character: 'yes !.u.s.! match'
test start of line: '.u.s.! yes match'
test end of line: 'yes match .u.s.'
<强>查询强>
SELECT *
FROM TestRegex
WHERE name REGEXP '(^|[^[:alnum:]_])[.]u[.]s[.]($|[^[:alnum:]_])';
<强>结论强>
返回所有阳性病例,没有阴性病例=&gt;所有测试用例都成功了。
[.]
用于句点字符而不是\\.
,我发现它在SQL表达式的上下文中更具可读性。[^a-zA-Z_0-9.!?#$]
。答案 2 :(得分:1)
这里的工作示例:http://www.sqlfiddle.com/#!2/5aa90d/9/0
SELECT name FROM tbl_name WHERE name REGEXP "[[:<:]]u\\.s\\.([^[:alnum:]]|$)"
基本上说美国。必须后跟任何非字母数字字符或字符串结尾的内容。
您可以将[:alnum:]
更改为[:alpha:]
以包含这是u.s.5 等结果,如果可取的话。
答案 3 :(得分:0)
只需使用此查询:
SELECT name FROM tbl_name WHERE name REGEXP ""[[:<:]]u\\.s\\.([[:blank:]]|$)"
由于您在end-of-word
之后已经有一个点,因此无需在RHS上使用[[:>:]]
s
。
答案 4 :(得分:0)
在mysql regexp manual中是一个特殊字符表以及如何转义主题。
像
一样进行查询SELECT name FROM tbl_name WHERE name REGEXP "[[:<:]]u[.]s[.][[:>:]]"
或
SELECT name FROM tbl_name WHERE name REGEXP "[[:<:]]u[[.period.]]s[[.period.]][[:>:]]"
将起作用