我构建了一个正则表达式,我尝试将它与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相同。
答案 0 :(得分:1)
单词边界\b
有时会表现得很奇怪,尤其是在与Unicode字符一起使用时。这是由于单词\w
的性质以及正则表达式的每种风格如何解释它。单词字符\w
通常定义为a-zA-Z0-9_
。启用Unicode匹配时,某些正则表达式包含单词字符集中的Unicode字符,而其他字符集则不包含。
为什么所有这些谈论单词字符?因为字边界\b
取决于字词\w
。 \b
是一个断言,可确保(^\w|\w$|\W\w|\w\W)
在该位置匹配。
元字符
\b
是一个像插入符和美元一样的锚 标志。它匹配的位置称为“单词边界”。 这个匹配是零长度。有三个不同的立场 符合词边界:
- 在字符串中的第一个字符之前,如果第一个字符是单词字符。
- 在字符串中的最后一个字符之后,如果最后一个字符是单词字符。
- 字符串中的两个字符之间,其中一个是单词字符,另一个不是单词字符。
简单地说:
\b
允许您执行“仅限整个单词”搜索 使用\bword\b
形式的正则表达式。一个“字 字符“是一个可以用来形成单词的字符。全部 不是“单词字符”的字符是“非单词 字符“。在各种风格中,字符[a-zA-Z0-9_]
都是 字符。这些也与短手角色相匹配 班\w
。味道显示“ascii”的字边界 风味比较只识别这些字符。
\w
代表“单词字符”,通常为[A-Za-z0-9_]
。注意 包含下划线和数字。
\B
是\b
的否定版本。\B
匹配每个位置 其中\b
没有。实际上,\B
匹配任何位置 两个字的字符以及两个非字之间的任何位置 字符。
\W
是[^\w]
的缩写,是\w
的否定版本。
(?:(?<=[^\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