[英]How to select records from mysql database by regex
我有一个regexp来验证用户的电子邮件地址。
/^(|(([A-Za-z0-9]+_+)|([A-Za-z0-9]+\-+)|([A-Za-z0-9]+\.+)|([A-Za-z0-9]+\++))*[A-Za-z0-9]+@((\w+\-+)|(\w+\.))*\w{1,63}\.[a-zA-Z]{2,})$/i"
在活动记录的帮助下,我想从数据库中获取其电子邮件地址与此正则表达式不匹配的所有用户。 我尝试了以下scope
来实现所需的结果,但我得到的只是ActiveRecord::Relation
。
scope :not_match_email_regex, :conditions => ["NOT email REGEXP ?'", /^(|(([A-Za-z0-9]+_+)|([A-Za-z0-9]+\-+)|([A-Za-z0-9]+\.+)|([A-Za-z0-9]+\++))*[A-Za-z0-9]+@((\w+\-+)|(\w+\.))*\w{1,63}\.[a-zA-Z]{2,})$/"]
这给了我以下查询:
SELECT `users`.* FROM `users` WHERE (email REGEXP '--- !ruby/regexp /^(|(([A-Za-z0-9]+_+)|([A-Za-z0-9]+\\-+)|([A-Za-z0-9]+\\.+)|([A-Za-z0-9]+\\++))*[A-Za-z0-9]+@((\\w+\\-+)|(\\w+\\.))*\\w{1,63}\\.[a-zA-Z]{2,})$/\n...\n')
我还尝试以下列方式定义此scope
,结果相同:
scope :not_match_email_regex, :conditions => ["email REGEXP '(|(([A-Za-z0-9]+_+)|([A-Za-z0-9]+\-+)|([A-Za-z0-9]+\.+)|([A-Za-z0-9]+\++))*[A-Za-z0-9]+@((\w+\-+)|(\w+\.))*\w{1,63}\.[a-zA-Z]{2,})'"]
它生成的查询是:
SELECT `users`.* FROM `users` WHERE (email REGEXP '(|(([A-Za-z0-9]+_+)|([A-Za-z0-9]+-+)|([A-Za-z0-9]+.+)|([A-Za-z0-9]+++))*[A-Za-z0-9]+@((w+-+)|(w+.))*w{1,63}.[a-zA-Z]{2,})')
如何获取与给定正则表达式匹配或不匹配的所有记录?
编辑12-11-30小修正部分根据@innocent_rifle的评论
这里建议的Regexp尝试进行与原始问题相同的匹配
1.在我第一次写它的解决方案时,我忘了你必须在字符串中逃脱\\
因为我在MySQL中直接测试。 在讨论Regexps时,在字符串中使用Regexps会让人感到困惑,所以我将使用这个表单,例如/dot\\./.source
"dot\\\\."
/dot\\./.source
(在Ruby中)将给出"dot\\\\."
。
2. MySQL中的REGEXP (手册为5.6,在5.0.67中测试)正在使用“字符串中的C转义语法”,因此WHERE email REGEXP '\\.'
仍然与WHERE email REGEXP '.'
相同WHERE email REGEXP '.'
,找到角色"."
你必须使用WHERE email REGEXP '\\\\.'
,要实现这一点,你必须使用代码.where([ 'email REGEXP ?', "\\\\\\\\."])
。 使用它更具可读性.where([ 'email REGEXP ?', /\\\\./.source ])
(MySQL需要2次转义)。 但是,我更喜欢使用.where([ 'email REGEXP ?', /[.]/.source ])
,然后我不必担心你需要多少逃脱。
3.你不需要在Regexp中转义"-"
,而不是在[]
使用它,只要该字符是第一个或最后一个。
我发现的一些错误:它是第一个正则表达式 - 或“|” 在你的表达式中,它应该是查询中的String,或者使用我喜欢的Regexp#source。 我认为最后还有一个额外的引用。 除此之外你真的确定正则表达式有效。 如果你在控制台上尝试一下字符串?
另请注意,您不会在db中捕获带NULL的电子邮件,在这种情况下,您必须添加(<your existing expr in parentheses>) OR IS NULL
我的MySQL版本中的Regexp语法。
我还测试了@Olaf Dietsche在他的建议中写的内容,似乎不需要它,但强烈建议遵循标准语法 ( NOT (expr REGEXP pat)
或expr NOT REGEXP pat
)。
我做了一些检查,必须更改这些内容:使用[A-Za-z0-9_]
代替\\w
,而\\+
无效,必须使用\\\\+
( "\\\\\\\\+"
如果字符串), [+]
(在Regexp或字符串中)更容易。
它导致在MySQL中遵循REGEXP
'^(([A-Za-z0-9]+_+)|([A-Za-z0-9]+-+)|([A-Za-z0-9]+[.]+)|([A-Za-z0-9]+[+]+))*[A-Za-z0-9]+@(([A-Za-z0-9]+-+)|([A-Za-z0-9]+[.]))*[A-Za-z0-9]{1,63}[.][a-zA-Z]{2,}$'
小改变建议
我完全不明白你的正则表达式,所以这只是改变你的正则表达式而不改变它会发现的东西。
首先:如上所述更改整个字符串
然后改变
(([A-Za-z0-9]+_+)|([A-Za-z0-9]+-+)|([A-Za-z0-9]+[.]+)|([A-Za-z0-9]+[+]+))*
至
([A-Za-z0-9]+[-+_.]+)*
和
@(([A-Za-z0-9]+-+)|([A-Za-z0-9]+[.]))*
至
@([A-Za-z]+[-.]+)*
最终代码 (如果您愿意,可以更改为..., :conditions => ...
语法)。 我试图让它找到与 @innocent_rifle 注释中相同的字符串 ,只在@
右边的表达式中添加"_"
。
.where([ 'NOT (email REGEXP ?)', /^([A-Za-z0-9]+[-+_.]+)*[A-Za-z0-9]+@([A-Za-z0-9]+[-._]+)*[A-Za-z0-9_]{1,63}[.][A-Za-z]{2,}$/.source ])
要验证电子邮件地址,您可能需要考虑如何查找或验证电子邮件地址 。 至少,这个regexp看起来有点简单。
根据MySQL - 正则表达式 ,正确的语法是
expr REGEXP pat
比赛,和
expr NOT REGEXP pat
或NOT (expr REGEXP pat)
相反的。 不要忘记第二个版本中的大括号。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.