elasticsearch 上的负前瞻正则表达式
negative lookahead regex on elasticsearch
我正在尝试对 elasticsearch 查询进行否定前瞻,
正则表达式是:
(?!.*charge)(?!.*encode)(?!.*relate).*night.*
我匹配的文本是:
credited back on night stay, still having issues with construction.
causing health issues due to a chemical being sprayed and causes eyes
to irritated.
我运气不好。有人可以帮忙吗?
ES 查询:
"query": {
"filtered": {
"query": {
"bool": {
"must_not": [
{
"regexp": {
"message": {
"value": "(?!.*charge)(?!.*encode)(?!.*relate).*night.*",
"flags_value": 65535
}
}
}
]
}
},
"filter": {
"match": {
"resNb": {
"query": "462031152161",
"type": "boolean"
}
}
}
}
}
您没有使用 锚点 进行前瞻。尝试在模式的开头使用“^”,它应该可以工作。
解决方案
您可以通过以下两种方式解决问题:
"value": "~(charge|encode|relate)night~(charge|encode|relate)",
或
.*night.*&~(.*(charge|encode|relate).*)
有一个可选的(因为它是开启的默认)
"flags" : "ALL"
它是如何工作的?
在常见的 NFA 正则表达式中,您通常会使用否定环视来帮助限制更通用的模式(那些看起来像 (?!...)
或 (?<!...)
的模式)。但是,在 ElasticSearch 中,您需要使用特定的 optional operators.
~
(代字号)是 补码,*用于否定紧随其后的原子。原子可以是单个符号,也可以是一组 subpatterns/alternatives 中的一组。
请注意,默认情况下,所有 ES 模式都锚定在字符串的开头和结尾,您永远不需要使用 Perl-like 和 .NET 以及其他 NFA 中常见的 ^
和 $
.
因此,
~(charge|encode|relate)
- 从字符串开头匹配除 charge
、encode
和 relate
之外的任何文本
night
- 匹配单词 night
~(charge|encode|relate)
- 匹配除 3 个子字符串中的任何一个以外的任何文本,直至字符串末尾。
在像 Perl 这样的 NFA 正则表达式中,您可以使用 :
编写该模式
/^(?:(?!charge|encode|relate).)*night(?:(?!charge|encode|relate).)*$/
第二种模式比较棘手:常见的 NFA 正则表达式在匹配时通常不会从一个位置跳到另一个位置,因此通常使用锚定在文本开头的前瞻。在这里,使用 INTERSECTION 我们可以只使用 2 个模式,其中一个匹配字符串 和 第二个也应该匹配字符串。
.*night.*
- 匹配整行(因为 .
匹配除换行符以外的任何符号,否则使用 (.|\n)*
),其中包含 night
&
- 和
~(.*(charge|encode|relate).*)
- 没有 charge
、encode
和 relate
子字符串的行。
一个类似 NFA Perl 的正则表达式看起来像
/^(?!.*(charge|encode|relate)).*night.*$/
我正在尝试对 elasticsearch 查询进行否定前瞻, 正则表达式是:
(?!.*charge)(?!.*encode)(?!.*relate).*night.*
我匹配的文本是:
credited back on night stay, still having issues with construction. causing health issues due to a chemical being sprayed and causes eyes to irritated.
我运气不好。有人可以帮忙吗?
ES 查询:
"query": {
"filtered": {
"query": {
"bool": {
"must_not": [
{
"regexp": {
"message": {
"value": "(?!.*charge)(?!.*encode)(?!.*relate).*night.*",
"flags_value": 65535
}
}
}
]
}
},
"filter": {
"match": {
"resNb": {
"query": "462031152161",
"type": "boolean"
}
}
}
}
}
您没有使用 锚点 进行前瞻。尝试在模式的开头使用“^”,它应该可以工作。
解决方案
您可以通过以下两种方式解决问题:
"value": "~(charge|encode|relate)night~(charge|encode|relate)",
或
.*night.*&~(.*(charge|encode|relate).*)
有一个可选的(因为它是开启的默认)
"flags" : "ALL"
它是如何工作的?
在常见的 NFA 正则表达式中,您通常会使用否定环视来帮助限制更通用的模式(那些看起来像 (?!...)
或 (?<!...)
的模式)。但是,在 ElasticSearch 中,您需要使用特定的 optional operators.
~
(代字号)是 补码,*用于否定紧随其后的原子。原子可以是单个符号,也可以是一组 subpatterns/alternatives 中的一组。
请注意,默认情况下,所有 ES 模式都锚定在字符串的开头和结尾,您永远不需要使用 Perl-like 和 .NET 以及其他 NFA 中常见的 ^
和 $
.
因此,
~(charge|encode|relate)
- 从字符串开头匹配除charge
、encode
和relate
之外的任何文本
night
- 匹配单词night
~(charge|encode|relate)
- 匹配除 3 个子字符串中的任何一个以外的任何文本,直至字符串末尾。
在像 Perl 这样的 NFA 正则表达式中,您可以使用
/^(?:(?!charge|encode|relate).)*night(?:(?!charge|encode|relate).)*$/
第二种模式比较棘手:常见的 NFA 正则表达式在匹配时通常不会从一个位置跳到另一个位置,因此通常使用锚定在文本开头的前瞻。在这里,使用 INTERSECTION 我们可以只使用 2 个模式,其中一个匹配字符串 和 第二个也应该匹配字符串。
.*night.*
- 匹配整行(因为.
匹配除换行符以外的任何符号,否则使用(.|\n)*
),其中包含night
&
- 和~(.*(charge|encode|relate).*)
- 没有charge
、encode
和relate
子字符串的行。
一个类似 NFA Perl 的正则表达式看起来像
/^(?!.*(charge|encode|relate)).*night.*$/