如何与Regexp进行复杂的字符串匹配?

我试图根据员工的注释(基于不同的数据输入样式而有所不同),在一些非结构化文本字段中在MYSQL中搜索模式。数据输入可能会记录以下内容供咖啡因使用:

User 1: 'caffeine: Never'
User 2: 'caffeine - Not much'
User 3: 'caffeine:  No' 
User 4: 'caffeine-No'

我正在尝试寻找一种搜索所有记录中显示“咖啡因” +(1个或多个空格或无空格)+(:或-或无字符)+(1个或多个空格或无空格)+的方法+ (不要以“ N”开头)

我尝试过的是:

从表格RLIKE [[:space:]] [[:punct:]] [[:: space:]] * [^ nN]';

表达式的第一部分似乎起作用,但是我在最后一部分的结果中发现了例外,排除了“ n”或“ N”,而且我不确定为什么不排除查询。我希望有人可以在这里澄清这一点。

xin11230 回答:如何与Regexp进行复杂的字符串匹配?

为什么会这样?

由于回溯,您仍在匹配这些句子。

因为您使用的是[^nN],所以它仍然可以匹配blankpunct。因此,这就是发生的情况(仅使用示例输入之一进行说明):

Caffeine[:blank:]*[:punct:]*[:blank:]*[^nN]为例(所有模式都以相同的方式运行)。

User 4: 'Caffeine-No'
         ^^^^^^^^       matches Caffeine literally
                 ^      matches [:blank:] zero times
                 ^      matches [:punct:] one time
                  ^     matches [:blank:] zero times
                  ^     N doesn't match `[^nN]`,let's backtrack to see if something else works
                 ^      matches [:punct:] zero times
                 ^      matches [:blank:] zero times
                 ^      - matches [^nN]

Good match due to backtracking

在上面,您的正则表达式允许[^nN]匹配-字符。正则表达式想要匹配某项,因此它将耗尽所有可能性,直到它匹配为止(或不再存在或不再存在)。

如何解决此问题?

解决此问题的一种方法是仅在[^nN]位置指定可能的字符(类似[0-9a-mo-z]等),但这会很快变得复杂。更好的替代方法如下:

See the SQL working here

select * from docs where content REGEXP 'Caffeine[[:blank:]]*[[:punct:]]*[[:blank:]]*[[:<:]][^nN]'

上面的行使用[[:<:]]断言该位置是单词边界的起点。其他语言使用\b表示相同的含义。这意味着它可以确保除[0-9a-zA-Z_]之外的任何字符都匹配到该位置的左侧,并且确保[0-9a-zA-Z_]中的任何字符都可以匹配到该位置的右侧。

在其他正则表达式引擎中,可以通过使用所有格修饰符(通常是+之后的.*+,例如|--------------------------------------------|------------------| | Column 1 | column 2 | |--------------------------------------------|------------------| |/fixed/sample_1 | 10 | |--------------------------------------------|------------------| |/fixed/sample_1/ | 15 | |--------------------------------------------|------------------| |/fixed/sample_1/sp1_level2 | 10 | |--------------------------------------------|------------------| |/fixed/sample_1/sp1_level2/sp1_level3 | 20 | |--------------------------------------------|------------------| |/fixed/sample_2/ | 25 | |--------------------------------------------|------------------| |/fixed/sample_2/sp2_level2/sp2_level3 | 20 | |--------------------------------------------|------------------| |/fixed/sample_3 | 30 | |--------------------------------------------|------------------| )来轻松实现相同的目的,但是MySQL尚无所有格令牌(AFAIK)。

,

不是试图猜测所有可能的变化,而是最简单的方法是剥离“咖啡因”和所有不是单词字符的内容,然后使用其余的内容。使用POSIX [:alnum:] (alphanumeric) character class并将其取反。

select regexp_replace(answer,'^Caffeine[^[:alnum:]]+','')
from quiz;

dbfiddle

然后解析剩余的内容。

本文链接:https://www.f2er.com/3157197.html

大家都在问