经过一段时间的工作和研究,我找到了完美的规则来检查[batt, lk, elem]
所有单词是否都在 2 个符号之间 ">;"> 以任何顺序。
在下一个示例中,"句子"由 " ;" 拆分,例如:
;first sentence; second sentece; third sentence;
正则表达式 -> (?=;.*batt)(?=;.*lk)(?=;.*elem)
真实例子:
; lk Buttle, batt; Probatton with LK elements; -> FOUND
;look Buttle; Proton with LK elements; -> NOT FOUND (not all 3 words are in the first OR in the second sentence)
;Brad Pitt the actor; LK elements in Battle; -> FOUND (the 3 words are in the second sentece)
;Brad Pitt the actor; LK elements in; Battle; -> not FOUND ("Battle" [root:'batt'] is in a different sentence)
当将此应用于 mySQL 查询时:
SELECT * FROM `table` pl WHERE pl.`description` REGEXP '(?=;.*batt)(?=;.*lk)(?=;.*elem)'
我发现正则表达式懒惰操作不起作用。
如何将该正则表达式转换为有效的正则表达式?
谢谢
这很贵。 您应该认真努力改进/标准化您的数据存储,以便更简单/更快地查询。
pl.`description` REGEXP 'batt[^;]*lk[^;]*elem|[^;]*lk[^;]*elem[^;]*batt'
这假设(基于您的示例输入(elem
始终跟在 lk
之后,并且batt
可以位于其他两个子字符串之前或之后。
这里有一个使用变量的小技巧。
有 3 个单词,这意味着只有 6 种组合可能。
因此,变量以 6 种组合的模式开始。
替换将其更改为对 3 个单词执行此操作的模式。
例如:
drop table if exists test;
create table test (id int, description varchar(100), rlikeit bool);
insert into test (id, description, rlikeit) values
(1,';lk elem batt;',true),
(2,';lk batt elem;',true),
(3,';elem lk batt;',true),
(4,';elem batt lk;',true),
(5,';batt lk elem;',true),
(6,';batt elem lk;',true),
(7,'; batt; lk; elem;',false),
(8,';batt batt batt;',false),
(9,'; lk Buttle, batt; Probatton with LK elements;',true),
(10,';look Buttle; Proton with LK elements;',false),
(11,';Brad Pitt the actor; LK elements in Battle;',true),
(12,';Brad Pitt the actor; LK elements in; Battle;',false);
set @pattern = ';x1x(2x3|3x2)|;x2x(1x3|3x1)|;x3x(1x2|2x1)';
-- set @pattern = '1x(2x3|3x2)|2x(1x3|3x1)|3x(1x2|2x1)'; -- shorter pattern
set @pattern = replace(replace(replace(replace(@pattern,
'x','[^;]*'),
'1','lk'),
'2','elem'),
'3','batt');
select *
from test
where description RLIKE @pattern;
选择将仅返回 id 的 1 到 6、9 和 11。
请注意,在一个更完整的正则表达式引擎中,它将使用类似 f.e 的模式来完成。 /;(?=[^;]*batt)(?=[^;]*lk)(?=[^;]*elem)[^;]*/i
.
但遗憾的是,MySQL REGEXP 语法不允许前瞻。