整个单词与MySQL中的点字符匹配

时间:2013-08-09 19:07:04

标签: mysql regex

在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\\.[[:>:]]"

任何建议都表示赞赏!

5 个答案:

答案 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:]_])'; 

SQLFiddle

<强>结论

返回所有阳性病例,没有阴性病例=&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.]][[:>:]]"

将起作用