MongoDB正则表达式选项'u'(UTF-8)

时间:2017-11-01 17:46:43

标签: regex mongodb utf-8

我构建了一个正则表达式,我尝试将它与MongoDB一起使用,但我没有预期的结果,因为我不知道如何启用UTF-8支持。

例如正则表达式:\b42\b
Example available here

应匹配:

42
hello 42
hello-42-

不匹配:

été42 
042
 4 2 

棘手的匹配就是这个:été42,没有UTF-8选项,它与正则表达式相匹配但不应该。

documentation未提及通常的u选项。

所以实际上我的查询是:

db.getCollection('collection_name').find(
{
    'title' : { $regex : '\\b42\\b', $options: 'i'}
});

我使用MongoDB 3.2版,但这个问题与3.4相同。

1 个答案:

答案 0 :(得分:1)

单词边界\b有时会表现得很奇怪,尤其是在与Unicode字符一起使用时。这是由于单词\w的性质以及正则表达式的每种风格如何解释它。单词字符\w通常定义为a-zA-Z0-9_。启用Unicode匹配时,某些正则表达式包含单词字符集中的Unicode字符,而其他字符集则不包含。

为什么所有这些谈论单词字符?因为字边界\b取决于字词\w\b是一个断言,可确保(^\w|\w$|\W\w|\w\W)在该位置匹配。

@Ωmega

上引用answerthis post
  

元字符\b是一个像插入符和美元一样的锚   标志。它匹配的位置称为“单词边界”。   这个匹配是零长度。有三个不同的立场   符合词边界:

     
      
  • 在字符串中的第一个字符之前,如果第一个字符是单词字符。
  •   
  • 在字符串中的最后一个字符之后,如果最后一个字符是单词字符。
  •   
  • 字符串中的两个字符之间,其中一个是单词字符,另一个不是单词字符。
  •   
     

简单地说:\b允许您执行“仅限整个单词”搜索   使用\bword\b形式的正则表达式。一个“字   字符“是一个可以用来形成单词的字符。全部   不是“单词字符”的字符是“非单词   字符“。在各种风格中,字符[a-zA-Z0-9_]都是   字符。这些也与短手角色相匹配   班\w。味道显示“ascii”的字边界   风味比较只识别这些字符。

     

\w代表“单词字符”,通常为[A-Za-z0-9_]。注意   包含下划线和数字。

     

\B\b的否定版本。 \B匹配每个位置   其中\b没有。实际上,\B匹配任何位置   两个字的字符以及两个非字之间的任何位置   字符。

     

\W[^\w]的缩写,是\w的否定版本。

代码

See this regex in use here

(?:(?<=[^\p{L}\p{N}])|^)42(?=[^\p{L}\p{N}]|$)

结果

输入

42
hello 42
hello-42-

été42 
042
 4 2 

输出

注意:以下是匹配发生的字符串。

42
hello 42
hello-42-

蒙戈

使用此mongo过滤器进行测试和验证:
{ $regex : '(?:(?<=[^\\p{L}\\p{N}])|^)42(?=[^\\p{L}\\p{N}]|$)' }

说明

  • (?:(?<=[^\p{L}\p{N}])|^)匹配以下任一项
    • (?<=[^\p{L}\p{N}])确保前面的内容是集合中的字符\p{L}\p{N}\p{L}是任何语言中的任意字母\p{N} }是任何语言中的任何数字)
    • ^在行首处断言位置
  • 42字符42字面意思
  • (?=[^\p{L}\p{N}]|$)确定以下任何一项匹配的积极前瞻
    • [^\p{L}\p{N}]匹配集\p{L}\p{N}
    • 的字符
    • $断言行尾的位置

其他选项

@Wiktor Stribiżew所述(在您提问的评论中),如果您可以使用PCRE正则表达式(*UCP),则可能还有其他选项。模式修饰符UCP(Unicode字符属性)允许正则表达式将字符串视为Unicode,这意味着\d\w被扩展为匹配除[0-9]和{{1}之外的其他Unicode字符}。

这样您就可以使用here

中的正则表达式[a-zA-Z0-9_]

蒙戈

使用此mongo过滤器进行测试和验证:
(*UCP)\b42\b