mysql - 如何使用 Regexp 进行复杂的字符串匹配?

标签 mysql regex regexp-like

我正在尝试在 MYSQL 中搜索一些非结构化文本字段的模式,基于员工的笔记,这些笔记因不同的数据输入样式而异。数据条目可能会记录以下咖啡因使用情况:

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

我正在尝试找到一种方法来搜索所有显示“Caffeine”的记录 +(1 个或更多空格或无空格)+(:或 - 或无字符)+(1 个或更多空格或无空格)+ (不是任何以“N”开头的东西)

我试过的是:

从表中选择 *,其中文本 RLIKE [[:space:]][[:punct:]][[:space:]]*[^nN]';

表达式的第一部分似乎有效,但我在最后一部分的结果中发现异常,不包括“n”或“N”,我不确定为什么我的查询没有排除。我希望有人可以在这里帮助澄清这一点。

最佳答案

为什么会这样?

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

因为您正在使用 [^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_] 中的任何字符匹配到位置的右侧。

在其他正则表达式引擎中,使用所有格量词(通常是 + 跟随量词,例如 .*+ )可以轻松实现相同的目的,但 MySQL 还没有所有格标记 (AFAIK)。

关于mysql - 如何使用 Regexp 进行复杂的字符串匹配?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/58717518/

相关文章:

mysql - 需要将 1 行数据转置为 1 列但多行

php - 检查电子邮件地址是否已被使用

python - 用于文本文件名称提取的正则表达式

oracle正则表达式来检查字符串包含字母和数字并且不包含特殊字符

regex - 从大约 5 个单词中以任意顺序匹配至少 3 个单词

mysql - 使用 DMS 复制数据库时出错

java - 如何使 JSP 函数仅在调用时运行?

php - 如何使用 str_getcsv() 并忽略引号之间的逗号?

regex - 捕获快速正则表达式的方法

sql - 从 STATION 查询以元音(即 a、e、i、o 或 u)开头的 CITY 名称列表